diff --git a/package.json b/package.json index 18bc703f6..46704e96a 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "@mapbox/mapbox-gl-style-spec": "13.11.0", "eventbusjs": "0.2.0", "geoportal-access-lib": "2.1.6", - "itowns": "2.19.0", + "itowns": "2.23.0", "leaflet": "1.5.1", "leaflet-draw": "1.0.4", "loglevel": "^1.6.7", diff --git a/src/Common-review/CSS/GPboostRelief.css b/src/Common-review/CSS/GPboostRelief.css new file mode 100644 index 000000000..1706ae36d --- /dev/null +++ b/src/Common-review/CSS/GPboostRelief.css @@ -0,0 +1,180 @@ +/* BOOST RELIEF */ + + div[id^=GPboostRelief-] { + font-size: 11px; + width: 150px; + } + + div[id^=GPboostRelief-] label { + display: block; + } + + div[id^=GPBoostReliefListContainer-] { + position: relative; + width: 100%; + height: 28px; + padding-left: 8px; + line-height: 28px; + } + + .GPlayerRelief, + .GPlayerReliefValue { + position: absolute; + top: 0; + } + + .GPlayerRelief { + width: calc(100% - 60px); + height: 28px; + padding-left: 8px; + } + + .GPlayerReliefValue { + width: 32px; + left: calc(100% - 40px); + line-height: 28px; + font-size: 10px; + font-style: italic; + cursor: default; + } + + /* Showing/hiding boost relief panel */ + + label[id^=GPshowBoostReliefPicto] { + display: inline-block; + } + + input[id^=GPshowBoostRelief-] + label { + display: block; + } + + input[id^=GPshowBoostRelief-]:checked + label { + display: none; + } + + input[id^=GPshowBoostRelief-] + label + div { + display: none; + } + + input[id^=GPshowBoostRelief-]:checked + label + div { + display: block; + } + + /* Showing layer advanced tools */ + + div[id^=GPboostRelief-] input[type="checkbox"]:checked + label + .GPlayerAdvancedToolsRelief { + max-height: 28px; + opacity: 1; + } + + .GPlayerAdvancedToolsRelief { + display: block; + position: relative; + width: 100%; + border-bottom : 1px dotted #CCC; + background-color : #FFF; + } + + .GPlayerReliefLayerId { + position: relative; + width: 100px; + height: 28px; + padding-left: 8px; + line-height: 28px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + /* Relief slider : general */ + + .GPlayerRelief input { + -webkit-appearance: none; + -moz-appearance: none; + background: none; + display: block; + width: 100%; + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; + cursor: pointer; + } + + .GPlayerRelief input[type="range"]:focus { + box-shadow: none; + outline: none; + } + + /* Relief slider : Chrome, Safari, Opera */ + + .GPlayerRelief input[type="range"]::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 3px; + } + + .GPlayerRelief input[type="range"]::-webkit-slider-thumb:before { + position: absolute; + top: 0; + right: 50%; + left: -200px; + height: 3px; + pointer-events: none; + } + + .GPlayerRelief input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + width: 9px; + height: 17px; + -webkit-appearance: none; + border: 2px solid #FFF; + background-color: #505050; + position: relative; + top: -7px; + } + + /* Relief slider : Firefox */ + + .GPlayerRelief input[type="range"]::-moz-range-track { + width: 80px; + height: 3px; + } + + .GPlayerRelief input[type="range"]::-moz-range-thumb { + width: 5px; + height: 13px; + border: 2px solid #FFF; + border-radius: 0; + box-shadow: 0; + background-color: #505050; + position: relative; + } + + /* Relief slider : IE */ + + .GPlayerRelief input[type="range"]::-ms-track { + border: 0; + border-color: transparent; + border-radius: 0; + border-width: 0; + color: transparent; + height: 3px; + width: 80px; + } + + .GPlayerRelief input[type="range"]::-ms-fill-lower, + .GPlayerRelief input[type="range"]::-ms-fill-upper { + background: transparent; + border-radius: 0; + } + + .GPlayerRelief input[type="range"]::-ms-thumb { + width: 5px; + height: 13px; + border: 2px solid #FFF; + background-color: #505050; + } + + .GPlayerRelief input[type="range"]::-ms-tooltip { + display: none; + } \ No newline at end of file diff --git a/src/Common-review/CSS/GPdrawing.css b/src/Common-review/CSS/GPdrawing.css new file mode 100644 index 000000000..a64b89e68 --- /dev/null +++ b/src/Common-review/CSS/GPdrawing.css @@ -0,0 +1,61 @@ +/* MOUSE POSITION */ + +/* Showing/hiding drawing panel */ + +label[id^=GPshowDrawingPicto-] { + display: inline-block; +} + +input[id^=GPshowDrawing-] + label { + display: block; +} + +input[id^=GPshowDrawing-]:checked + label { + display: none; +} + +input[id^=GPshowDrawing-] + label + div { + display: none; +} + +input[id^=GPshowDrawing-]:checked + label + div { + display: block; +} + +/* General panels */ + +div[id^=GPdrawingPanel-] { + width: 240px; + overflow: hidden; +} + +/* Basic infos */ + +div[id^=GPdrawingBasicPanel-] { + padding: 10px 15px; +} + +.GPdrawingLabel, +.GPdrawingCoords { + display: inline-block; + line-height: 20px; +} + +.GPdrawingLabel { + width: 80px; + font-weight: bold; +} + +.GPdrawingCoords { + width: 110px; +} + +/* markers selector */ +.marker-input-radio { + display : none ; +} + +input.marker-input-radio:checked + label { + border: 1px solid red; +} + diff --git a/src/Common-review/CSS/GPelevationPath.css b/src/Common-review/CSS/GPelevationPath.css new file mode 100644 index 000000000..bd8c57ef1 --- /dev/null +++ b/src/Common-review/CSS/GPelevationPath.css @@ -0,0 +1,451 @@ +div[id^=GPelevationPathPanelInfo] { + display: none; /* on n'affiche pas le bouton d'information par defaut */ +} + +/* Calc waiting */ + +.GPelevationPathCalcWaitingContainerVisible, +.GPelevationPathCalcWaitingContainerHidden { + position: absolute; + top: 32px; + bottom: 0; + left: 0; + right: 0; + background-color: rgba(255,255,255,0.9); + font-size: 1.5em; + font-weight: bold; + overflow: hidden; +} + +.GPelevationPathInformationsContainerVisible, +.GPelevationPathInformationsContainerHidden { + position: absolute; + top: 32px; + bottom: 0; + left: 0; + right: 0; + background-color: rgba(255,255,255,0.9); + font-size: 13px; + font-weight: bold; + overflow: hidden; +} + +.GPelevationPathCalcWaitingContainerVisible { + display: -webkit-flex; + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} + +.GPelevationPathInformationsContainerVisible { + display: -webkit-flex; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + flex-direction: column; +} + +.GPelevationPathCalcWaitingContainerHidden, +.GPelevationPathInformationsContainerHidden { + display: none; +} + +.GPelevationPathCalcWaiting, +.GPelevationPathInformations { + margin: auto; +} + +.GPelevationPathInformations { + font-size: 0.8em; +} + +.GPelevationPathCalcWaitingContainerVisible, +.GPelevationPathCalcWaitingContainerHidden, +.GPelevationPathInformationsContainerVisible, +.GPelevationPathInformationsContainerHidden { + border-radius: 5px; +} + +/* CSS : Raw */ + +#profileElevationRaw { + resize: none; + padding: unset; +} + +/* CSS : default */ + +#profileElevationByDefault { + display:-webkit-flex; + display:-webkit-box; + display:-ms-flexbox; + display:flex; + -webkit-box-orient:vertical; + -webkit-box-direction:normal; + -webkit-flex-direction:column; + -ms-flex-direction:column; + flex-direction:column; + height:100%; +} + +.profile-box { + height: calc(100% - 15px); + display:-webkit-flex; + display:-webkit-box; + display:-ms-flexbox; + display:flex; + -webkit-flex:1; + -webkit-box-flex:1; + -ms-flex:1; + flex:1; + -webkit-box-orient:horizontal; + -webkit-box-direction:normal; + -webkit-flex-direction:row; + -ms-flex-direction:row; + flex-direction:row; +} + +.profile-content { + -webkit-flex:1; + -webkit-box-flex:1; + -ms-flex:1; + flex:1; + -webkit-justify-content:center; + -webkit-box-pack:center; + -ms-flex-pack:center; + justify-content:center; + -webkit-box-align:center; + -webkit-align-items:center; + -ms-flex-align:center; + align-items:center; +} + +.profile-z-vertical, +.profile-z-vertical ul, +.profile-x-horizontal, +.profile-x-horizontal ul { + display:-webkit-flex; + display:-webkit-box; + display:-ms-flexbox; + display:flex; + /*justify-content:center;*/ + -webkit-align-items:center; + -webkit-box-align:center; + -ms-flex-align:center; + align-items:center; +} + + +.profile-z-vertical, +.profile-z-vertical ul, +.profile-content +{ + -webkit-box-orient:vertical; + -webkit-box-direction:normal; + -webkit-flex-direction:column; + -ms-flex-direction:column; + flex-direction:column; + height:100%; +} + +.profile-z-vertical ul, +.profile-x-horizontal ul{ + /*padding:0;*/ + margin:0; + list-style-type:none; +} + +.profile-z-vertical{ + /*background:green;*/ + -webkit-flex:0 1 auto; + -webkit-box-flex:0; + -ms-flex:0 1 auto; + flex:0 1 auto; + +} +.profile-z-vertical ul{ + /*background:pink;*/ + -webkit-justify-content:space-between; + -webkit-box-pack:justify; + -ms-flex-pack:justify; + justify-content:space-between; + padding:2px 5px 2px 2px; + /*border-right:1px solid #888;*/ +} +.profile-z-vertical .profile-unit{ + /*background:gray;*/ + width:100%; + text-align:center; + /*padding:5px 5px 2px 2px;*/ +} +.profile-content{ + /*background:yellow;*/ + /*flex:1 0 auto;*/ + +} +.profile-content ul { + background:white; + -webkit-flex:1 0 auto; + -webkit-box-flex:1; + -ms-flex:1 0 auto; + flex:1 0 auto; + height:100%; + width:100%; + -webkit-justify-content:flex-start; + -webkit-box-pack:start; + -ms-flex-pack:start; + justify-content:flex-start; + -webkit-align-items:flex-end; + -webkit-box-align:end; + -ms-flex-align:end; + align-items:flex-end; + + margin:0; + padding:0; + +} +.profile-x-horizontal{ + /*background:blue;*/ + -webkit-flex:0 1 auto; + -webkit-box-flex:0; + -ms-flex:0 1 auto; + flex:0 1 auto;; + width:100%; + height: 15px +} +.profile-x-horizontal ul{ + /*background:orange;*/ + -webkit-justify-content:space-between; + -webkit-box-pack:justify; + -ms-flex-pack:justify; + justify-content:space-between; + /*padding:5px 2px 2px 2px;*/ + width:100%; + /*border-top:1px solid #888;*/ +} + +.profile-x-fleche { + width: 0; + height: 0; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid green; +} + +.profile-z-fleche { + width: 0; + height: 0; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid red; +} + +.profile-z-axis { + border-right: none; + border-left: solid 2px #888; + cursor: default; +} + +.profile-x-axis { + border-top: none; + border-bottom: solid 2px #888; + cursor: default; +} + +ul#profile-data li.percent { + display: inline-block; + vertical-align: bottom; + background-color: #C77A04; + opacity : 0.3; + border-top: solid 1px; + border-radius: 2px; + cursor: pointer; +} + +li.axe span.bottom-axis { + vertical-align: bottom; +} + +ul#profile-data .percent:hover { + display: inline-block; + vertical-align: bottom; + background-color: #f00; +} + +.v0 { height: 0%; } +.v1 { height: 1%; } +.v2 { height: 2%; } +.v3 { height: 3%; } +.v4 { height: 4%; } +.v5 { height: 5%; } +.v6 { height: 6%; } +.v7 { height: 7%; } +.v8 { height: 8%; } +.v9 { height: 9%; } +.v10 { height: 10%; } +.v11 { height: 11%; } +.v12 { height: 12%; } +.v13 { height: 13%; } +.v14 { height: 14%; } +.v15 { height: 15%; } +.v16 { height: 16%; } +.v17 { height: 17%; } +.v18 { height: 18%; } +.v19 { height: 19%; } +.v20 { height: 20%; } +.v21 { height: 21%; } +.v22 { height: 22%; } +.v23 { height: 23%; } +.v24 { height: 24%; } +.v25 { height: 25%; } +.v26 { height: 26%; } +.v27 { height: 27%; } +.v28 { height: 28%; } +.v29 { height: 29%; } +.v30 { height: 30%; } +.v31 { height: 31%; } +.v32 { height: 32%; } +.v33 { height: 33%; } +.v34 { height: 34%; } +.v35 { height: 35%; } +.v36 { height: 36%; } +.v37 { height: 37%; } +.v38 { height: 38%; } +.v39 { height: 39%; } +.v40 { height: 40%; } +.v41 { height: 41%; } +.v42 { height: 42%; } +.v43 { height: 43%; } +.v44 { height: 44%; } +.v45 { height: 45%; } +.v46 { height: 46%; } +.v47 { height: 47%; } +.v48 { height: 48%; } +.v49 { height: 49%; } +.v50 { height: 50%; } +.v51 { height: 51%; } +.v52 { height: 52%; } +.v53 { height: 53%; } +.v54 { height: 54%; } +.v55 { height: 55%; } +.v56 { height: 56%; } +.v57 { height: 57%; } +.v58 { height: 58%; } +.v59 { height: 59%; } +.v60 { height: 60%; } +.v61 { height: 61%; } +.v62 { height: 62%; } +.v63 { height: 63%; } +.v64 { height: 64%; } +.v65 { height: 65%; } +.v66 { height: 66%; } +.v67 { height: 67%; } +.v68 { height: 68%; } +.v69 { height: 69%; } +.v70 { height: 70%; } +.v71 { height: 71%; } +.v72 { height: 72%; } +.v73 { height: 73%; } +.v74 { height: 74%; } +.v75 { height: 75%; } +.v76 { height: 76%; } +.v77 { height: 77%; } +.v78 { height: 78%; } +.v79 { height: 79%; } +.v80 { height: 80%; } +.v81 { height: 81%; } +.v82 { height: 82%; } +.v83 { height: 83%; } +.v84 { height: 84%; } +.v85 { height: 85%; } +.v86 { height: 86%; } +.v87 { height: 87%; } +.v88 { height: 88%; } +.v89 { height: 89%; } +.v90 { height: 90%; } +.v91 { height: 91%; } +.v92 { height: 92%; } +.v93 { height: 93%; } +.v94 { height: 94%; } +.v95 { height: 95%; } +.v96 { height: 96%; } +.v97 { height: 97%; } +.v98 { height: 98%; } +.v99 { height: 99%; } +.v100 { height: 100%; } + +/* CSS : D3 */ + +.axis-d3 > text { + fill: rgb(94, 94, 94); + font-family: Verdana; + font-size: 10px; + opacity: 1; + text-anchor: end; +} + +.axis-d3 { + fill: none; + stroke: #5E5E5E; + stroke-width: 1; + shape-rendering: crispEdges; +} + +.area-d3 { + fill: #C77A04; + stroke: #5E5E5E; + stroke-width: 0; + fill-opacity: 0.4; +} + +.line-d3 { + fill: none; + stroke: #C77A04; + stroke-width: 1px; +} + +.grid-d3 .tick { + stroke: lightgrey; + opacity: 0.7; +} + +.grid-d3 path { + stroke-width: 0; +} + +.grid-d3 .tick { + stroke: lightgrey; + opacity: 0.7; +} + +.grid-d3 path { + stroke-width: 0; +} + +.overlay-d3 { + fill: none; + pointer-events: all; +} + +.focusLine-d3 { + fill: none; + stroke: #C77A04; + stroke-width: 0.5px; +} + +.focusCircle-d3 { + fill: #C77A04; +} + +div.tooltip-d3 { + position: inherit;; + text-align: left; + width: 80px; + height: 45px; + padding: 5px; + font: 8px sans-serif; + background: white; + border: 0px; + border-radius: 8px; + pointer-events: none; +} diff --git a/src/Common-review/CSS/GPgeneralWidget.css b/src/Common-review/CSS/GPgeneralWidget.css new file mode 100644 index 000000000..2c0c81be1 --- /dev/null +++ b/src/Common-review/CSS/GPgeneralWidget.css @@ -0,0 +1,228 @@ +/* Widgets : general */ + +.GPwidget { + position: absolute; + font-family: "Helvetica Neue",Arial,Helvetica,sans-serif; + font-size: 13px; + color: #333; +} + +.GPwidget input[type='text'], +.GPwidget input[type='button'] { + -webkit-appearance: none; + color: #333333; +} + +.GPwidget input[type="checkbox"] { + display: none; +} + +.GPwidget select { + padding-left: 3px; + border-radius: 3px; +} + +.GPwidget form { + margin-bottom: 0; +} + +.GPwidget * { + box-sizing: border-box; + background-repeat: no-repeat; +} + +/* waiting */ + +.GPwaiting { + background-image : url("img/waiting.gif"); + background-position : center center; + background-repeat : no-repeat; +} + +/* General panels */ + +.GPpanel { + background-color: #FFF; +} + +.GPpanelHeader { + position: relative; + width: 100%; +} + +.GPpanelTitle { + width: 100%; + height: 100%; + text-align: center; + font-weight: bold; +} + +.GPpanelClose, .GPpanelReduce, .GPpanelInfo { + position: absolute; + cursor: pointer; +} + +/* Showing/hiding advanced panels */ + +.GPshowAdvancedToolPicto { + position: relative; + box-sizing: border-box; + cursor: pointer; +} + +.GPshowAdvancedToolOpen { + position: absolute; + display: block; + box-sizing: border-box; +} + +/* Flex inputs */ + +.GPflexInput { + display: -webkit-flex; + display: -ms-flexbox; + display: -webkit-box; + display: flex; + transition: max-height 0.3s ease-out, opacity 0.3s ease-out; +} + +/* FIXME tempory hack with :not(.GPlocationOriginHidden) ! +.GPflexInput > *:not(.GPlocationOriginHidden) */ +.GPflexInput > * { + display: block; + height: 28px; + line-height: 26px; + border: 1px solid #999; + border-radius: 0; +} + +.GPflexInput *:not(:last-child) { + border-right:none; +} + +.GPflexInput *:first-child { + border-radius: 3px 0 0 3px; +} + +.GPflexInput *:last-child { + border-radius: 0 3px 3px 0; +} + +.GPflexInput > *:not(input) { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.GPflexInput > input { + -webkit-flex: 1; + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1; + padding: 0 5px; + min-width: 0; +} + +.GPflexInput > select { + -webkit-flex: 1; + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1; + padding-right: 7px; +} + +.GPflexInput > label { + background-color: #F2F2F2; + color: #666; + padding-left: 7px; + padding-right: 9px; + cursor: pointer; +} + +/* Particular inputs */ + +.GPinputSelect { + display: block; + height: 28px; + line-height: 26px; + margin: auto; + border: 1px solid #999; + color: #333; + cursor: pointer; +} + +input.GPinputSubmit { + display: block; + width: 80px; + margin: auto; + height: 28px; + line-height: 26px; + padding: 0; + background: none; + border: none; + border-radius: 3px; + font-family: "Helvetica Neue",Arial,Helvetica,sans-serif; + color: #FFF; + font-weight: bold; + opacity: 0.8; + transition: opacity 0.2s ease-out; + cursor: pointer; +} + +input.GPinputSubmit:hover { + opacity: 1; +} + +/* Autocomplete/geocode results */ + +.GPautoCompleteList, +.GPadvancedAutoCompleteList { + z-index: 2; + display: none; + position: absolute; + max-height: 140px; + background-color: #FFF; + border: 1px solid #999; + overflow-y: hidden; +} + +.GPadvancedAutoCompleteList { + width: calc(100% - 28px); + border-top: none; + font-size: 0.9em; +} + +.GPautoCompleteProposal { + width: 100%; + height: 28px; + line-height: 16px; + padding: 6px 10px; + color: #5E5E5E; + font-size: 1.0em; + overflow: hidden; + white-space: nowrap; + text-overflow:ellipsis; + cursor: pointer; +} + +.GPautoCompleteProposal:hover { + color: #000000; + background-color: #CEDBEF +} + +/* Showing additional hidden options */ + +.GPshowMoreOptions { + display: block; + position: absolute; + width: 28px; + height: 28px; + cursor: pointer; + transition: all 0.5s ease-out 0s; +} + +input[type="checkbox"]:checked + .GPshowMoreOptions { + -webkit-transform: rotateX(180deg); + transform: rotateX(180deg); + /* bottom: 90px; */ +} diff --git a/src/Common-review/CSS/GPgetFeatureInfo.css b/src/Common-review/CSS/GPgetFeatureInfo.css new file mode 100644 index 000000000..422d8878d --- /dev/null +++ b/src/Common-review/CSS/GPgetFeatureInfo.css @@ -0,0 +1,29 @@ +/* GET FEATURE INFO */ + +label[id^=GPgetFeatureInfoPicto] { + display: inline-block; +} + +div[id^=GPgetFeatureInfo-] + label { + display: block; +} + +span[id^=GPgetFeatureInfoActivate], +span[id^=GPgetFeatureInfoDeactivate] { + position: absolute; + display: block; + transition: border-radius 0.5s ease-out 0s, opacity 0.5s ease-out 0s; +} + +span[id^=GPgetFeatureInfoActivate] { + background-position: 0 0; + opacity: 1; +} + +span[id^=GPgetFeatureInfoDeactivate] { + opacity: 0; +} + +div[id^=GPgetFeatureInfo-] input[type="checkbox"]:not(:checked) + label[id^=GPgetFeatureInfoPicto] span[id^=GPgetFeatureInfoDeactivate] { + opacity: 1; +} diff --git a/src/Common-review/CSS/GPisochron.css b/src/Common-review/CSS/GPisochron.css new file mode 100644 index 000000000..f9af5195b --- /dev/null +++ b/src/Common-review/CSS/GPisochron.css @@ -0,0 +1,309 @@ +/* ISOCHRON */ + +div[id^=GPisochron-] { + top: 140px; +} + +/* Showing/hiding mouse position panel */ + +label[id^=GPshowIsochronPicto] { + display: inline-block; +} + +input[id^=GPshowIsochron-] + label { + display: block; +} + +input[id^=GPshowIsochron-]:checked + label { + display: none; +} + +input[id^=GPshowIsochron-] + label + div { + display: none; +} + +input[id^=GPshowIsochron-]:checked + label + div { + display: block; +} + +/* General panels */ + +div[id^=GPisochronPanel-] { + width: 280px; +} + +/* Calc waiting */ + +.GPisochronCalcWaitingContainerVisible, +.GPisochronCalcWaitingContainerHidden { + position: absolute; + top: 32px; + bottom: 0; + left: 0; + right: 0; + background-color: rgba(255,255,255,0.9); + font-size: 1.5em; + font-weight: bold; + overflow: hidden; +} + +.GPisochronCalcWaitingContainerVisible { + display: -webkit-flex; + display: -ms-flexbox; + display: -webkit-box; + display: flex; +} + +.GPisochronCalcWaitingContainerHidden { + display: none; +} + +.GPisochronCalcWaiting { + margin: auto; +} + +/* Isochron form */ + +form[id^=GPisochronForm] { + padding: 15px; +} + +.GPisochronFormMini { + max-height: 58px; + overflow: hidden; +} + +.GPisochronFormMini div[id^="GPisochronReset-"], +.GPisochronFormMini label[id^="GPshowIsoExclusionsPicto-"] { + display: none; +} + +.GPisochronOriginVisible { + display: block; +} + +.GPisochronOriginHidden { + display: none; +} + +.GPisochronOriginPointerImg { + width: 28px; + background-color: #F2F2F2; + cursor: pointer; +} + +input[id^="GPisochronOriginPointer"] + .GPisochronOriginPointerImg { + background-position: -1px -1px; +} + +input[id^="GPisochronOriginPointer"]:checked + .GPisochronOriginPointerImg { + background-position: -29px -1px; +} + +input[id^=GPisochronSubmit] { + margin-top: 5px; +} + +/* Alternative choice */ + +div[id^=GPisochronChoice] { + display: -webkit-flex; + display: -ms-flexbox; + display: -webkit-box; + display: flex; + width: 160px; + -webkit-justify-content: space-between; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + margin: auto; + margin-top: 15px; + margin-bottom: 5px; +} + +.GPisochronChoiceAlt input { + display: none; +} + +.GPisochronChoiceAltImg { + display: block; + width: 28px; + height: 28px; + margin: auto; + cursor: pointer; +} + +input[id^=GPisochronChoiceAltChron] + .GPisochronChoiceAltImg { + background-position: -56px 0; +} + +input[id^=GPisochronChoiceAltChron]:checked + .GPisochronChoiceAltImg { + background-position: -84px 0; +} + +input[id^=GPisochronChoiceAltDist] + .GPisochronChoiceAltImg { + background-position: -112px 0; +} + +input[id^=GPisochronChoiceAltDist]:checked + .GPisochronChoiceAltImg { + background-position: -140px 0; +} + +.GPisochronChoiceAlt span { + cursor: pointer; + display:block; + color: #999; +} + +.GPisochronValueHidden { + display: none; +} + +div[id^=GPisochronValueChron], +div[id^=GPisochronValueDist] { + width: 220px; + margin: auto; +} + +/* Mode choice */ + +div[id^=GPisochronModeChoice] { + display: -webkit-flex; + display: -ms-flexbox; + display: -webkit-box; + display: flex; + -webkit-justify-content: space-between; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + margin: 15px 0; +} + +.GPisochronModeLabel { + display: block; + text-align: center; + margin-bottom: 5px; +} + +div[id^=GPisochronTransportChoice] input { + display: none; +} + +.GPisochronTransportImg { + display: inline-block; + width: 28px; + height: 28px; + cursor: pointer; +} + +.GPisochronTransportImg:first-of-type { + margin-left: 18px; + margin-right: 10px; +} + +input[id^=GPisochronTransportCar] + .GPisochronTransportImg { + background-position: -168px 0; +} + +input[id^=GPisochronTransportCar]:checked + .GPisochronTransportImg { + background-position: -196px 0; +} + +input[id^=GPisochronTransportPedestrian] + .GPisochronTransportImg { + background-position: -224px 0; +} + +input[id^=GPisochronTransportPedestrian]:checked + .GPisochronTransportImg { + background-position: -252px 0; +} + +select[id^=GPisochronDirectionSelect] { + width: 80px; +} + +/* Showing/hiding exclusions */ + +input[id^=GPshowIsoExclusions] { + display: none; +} + +.GPshowIsoExclusionsPicto { + top: 250px; + right: 0; + transition: all 0.5s ease-out 0s; +} + +input[id^=GPshowIsoExclusions] + label + div[id^=GPisoExclusions] { + max-height: 0; + opacity: 0; + margin-bottom: 0; +} + +input[id^=GPshowIsoExclusions]:checked + label + div[id^=GPisoExclusions] { + display: block; + max-height: 60px; + opacity: 1; + margin-bottom: 15px; +} + +/* Exclusions */ + +div[id^=GPisoExclusions] { + transition: max-height 0.5s ease-in-out 0.25s, opacity 0.5s ease-in-out 0.25s, margin 0.3s ease-in-out 0.25s; + overflow: hidden; +} + +.GPisoExclusionsLabel { + display: block; + text-align: center; + margin-bottom: 10px; + font-weight: bold; + line-height: 16px; +} + +.GPisoExclusionsOptions { + display: -webkit-flex; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-justify-content: space-around; + -ms-flex-pack: distribute; + justify-content: space-around; +} + +.GPisoExclusionsOption { + display: block; + height: 28px; + line-height: 26px; + color: #A77; + background-color: #FEE; + padding-left: 28px; + padding-right: 5px; + border: 1px solid #A77; + border-radius: 3px; + cursor: pointer; +} + +input:checked + .GPisoExclusionsOption { + background-color: #EFE; + background-position: 0 -28px; + color: #797; + border: 1px solid #797; +} + +/* Reset picto */ +div[id^=GPisochronReset] { + position: absolute; + margin-top: 5px; + width: 28px; + height: 28px; + border-radius: 3px; + opacity: 0.8; + background-position: -281px 0; + transition: opacity 0.2s ease-out; + cursor: pointer; +} + +div[id^=GPisochronReset]:hover { + opacity: 1; +} diff --git a/src/Common-review/CSS/GPlayerSwitcher.css b/src/Common-review/CSS/GPlayerSwitcher.css new file mode 100644 index 000000000..b5f19732e --- /dev/null +++ b/src/Common-review/CSS/GPlayerSwitcher.css @@ -0,0 +1,402 @@ +/* LAYER SWITCHER */ + +div[id^=GPlayerSwitcher-] { + font-size: 11px; +} + +div[id^=GPlayerSwitcher-] [draggable] { + -moz-user-select: none; + -khtml-user-select: none; + -webkit-user-select: none; + user-select: none; + /* Required to make elements draggable in old WebKit */ + -khtml-user-drag: element; + -webkit-user-drag: element; +} + +/* Manage opening of the components through hiden checkboxes */ + +div[id^=GPlayerSwitcher-] input[type="checkbox"] + div, +div[id^=GPlayerSwitcher-] input[type="checkbox"] + label + div { + max-height: 0px; +} + +div[id^=GPlayerSwitcher-] label { + display: block; +} + +/* Showing/hiding layers list */ + +label[id^=GPshowLayersListPicto] { + position: relative; + float: right; + display: block; + opacity: 1; + transition: opacity 0.5s ease-out 0s, box-shadow 0.5s ease-out 0s, border 0.5s ease-out 0s, border-radius 0.5s ease-out 0s; + cursor: pointer; +} + +span[id^=GPshowLayersListOpen], +span[id^=GPshowLayersListClose] { + position: absolute; + display: block; + transition: border-radius 0.5s ease-out 0s, opacity 0.5s ease-out 0s; +} + +span[id^=GPshowLayersListOpen] { + background-position: 0 0; + opacity: 1; +} + +span[id^=GPshowLayersListClose] { + opacity: 0; +} + +div[id^=GPlayerSwitcher-] input[type="checkbox"]:checked + div + label[id^=GPshowLayersListPicto] { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +div[id^=GPlayerSwitcher-] input[type="checkbox"]:checked + div + label[id^=GPshowLayersListPicto] span[id^=GPshowLayersListClose] { + opacity: 1; +} + +/* Layers list */ + +div[id^=GPlayersList] { + position: relative; + width: 180px; + border-bottom-right-radius: 0; + opacity: 0; + overflow: auto; + transition: max-height 0.5s ease-out 0s, opacity 0.5s ease-out 0.25s; +} + +div[id^=GPlayerSwitcher-] input[type="checkbox"]:checked + div[id^=GPlayersList] { + max-height: 232px; + opacity: 1; + transition: max-height 0.5s ease-in 0s, opacity 0.25s ease-in 0s; +} + +/* Layer : general */ + +.GPlayerSwitcher_layer { + position: relative; + top: 0; + background-color: #FFF; + border-bottom: 1px dotted #CCC; + overflow: hidden; +} + +div[id^=GPlayersList] .GPlayerSwitcher_layer:last-child { + border-bottom: none; +} + +.GPlayerBasicTools, +.GPlayerAdvancedTools { + position: relative; + width: 100%; + height: 28px; +} + +.GPlayerVisibility, +.GPlayerInfo, +.GPlayerInfoOpened, +.GPlayerRemove { + width: 28px; + height: 28px; + cursor: pointer; +} + +.GPlayerVisibility, +.GPlayerName, +.GPlayerInfo, +.GPlayerInfoOpened, +.GPlayerRemove, +.GPlayerOpacity, +.GPlayerOpacityValue { + position: absolute; + top: 0; +} + +.GPghostLayer { + opacity: 0; +} + +/* Layer basic tools */ + +.GPlayerBasicTools { + background-color: #FFF; +} + +.GPlayerVisibility { + left: 0; + background-position: -28px 0; +} + +input[type="checkbox"]:checked + .GPlayerVisibility { + background-position: 0 0; +} + +.GPlayerName { + left: 28px; + width: calc(100% - 56px); + line-height: 28px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + padding-left: 4px; + cursor: move; +} + +.outOfRange .GPlayerName { + color: #AAA; +} + +/* Showing layer advanced tools */ + +.GPshowLayerAdvancedTools { + top: 0; + right: 0; + background-position: -112px 0; +} + +.GPlayerAdvancedTools { + display: block; + max-height: 0; + opacity: 0; + transition: max-height 0.5s ease-out 0s, opacity 0.5s ease-out 0s; +} + +div[id^=GPlayerSwitcher-] input[type="checkbox"]:checked + label + .GPlayerAdvancedTools { + max-height: 28px; + opacity: 1; +} + +/* Layer advanced tools */ + +.GPlayerInfo { + left: 0; + background-position: -55px 0; +} + +.GPlayerInfoOpened { + left: 0; + background-position: -83px 0; +} + +.GPlayerOpacity { + left: 28px; + width: calc(100% - 100px); + height: 28px; + padding-left: 8px; +} + +.GPlayerOpacityValue { + width: 32px; + left: calc(100% - 60px); + line-height: 28px; + font-size: 10px; + font-style: italic; + cursor: default; +} + +.GPlayerRemove { + right: 0; + background-position: -140px 0; +} + +/* Opacity slider : general */ + +.GPlayerOpacity input { + -webkit-appearance: none; + -moz-appearance: none; + background: none; + display: block; + width: 100%; + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; + cursor: pointer; +} + +.GPlayerOpacity input[type="range"]:focus { + box-shadow: none; + outline: none; +} + +/* Opacity slider : Chrome, Safari, Opera */ + +.GPlayerOpacity input[type="range"]::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 3px; +} + +.GPlayerOpacity input[type="range"]::-webkit-slider-thumb:before { + position: absolute; + top: 0; + right: 50%; + left: -200px; + height: 3px; + pointer-events: none; +} + +.GPlayerOpacity input[type="range"]::-webkit-slider-thumb { + width: 9px; + height: 17px; + -webkit-appearance: none; + border: 2px solid #FFF; + background-color: #505050; + position: relative; + top: -7px; +} + +/* Opacity slider : Firefox */ + +.GPlayerOpacity input[type="range"]::-moz-range-track { + width: 80px; + height: 3px; +} + +.GPlayerOpacity input[type="range"]::-moz-range-thumb { + width: 5px; + height: 13px; + border: 2px solid #FFF; + border-radius: 0; + box-shadow: 0; + background-color: #505050; + position: relative; +} + +/* Opacity slider : IE */ + +.GPlayerOpacity input[type="range"]::-ms-track { + border: 0; + border-color: transparent; + border-radius: 0; + border-width: 0; + color: transparent; + height: 3px; + width: 80px; +} + +.GPlayerOpacity input[type="range"]::-ms-fill-lower, +.GPlayerOpacity input[type="range"]::-ms-fill-upper { + background: transparent; + border-radius: 0; +} + +.GPlayerOpacity input[type="range"]::-ms-thumb { + width: 5px; + height: 13px; + border: 2px solid #FFF; + background-color: #505050; +} + +.GPlayerOpacity input[type="range"]::-ms-tooltip { + display: none; +} + +/* Layer info panel */ + +div[id^=GPlayerInfoPanel] { + position: absolute; + top: 0; + overflow-y: hidden; + padding-top: 10px; + padding-bottom: 10px; +} + +.GPlayerInfoPanelOpened { + display: block; +} + +.GPlayerInfoPanelClosed { + display: none; +} + +div[id^=GPlayerInfoContent] { + position: relative; + width: 280px; + max-height: 200px; + overflow-y: auto; + padding-left: 10px; + padding-right: 10px; +} + +div[id^=GPlayerInfoTitle] { + width: calc(100% - 52px); + margin: auto; + margin-bottom: 10px; + padding-bottom: 5px; + text-align: center; + font-size: 1.1em; + font-weight: bold; +} + +div[id^=GPlayerInfoQuicklook] { + position: absolute; + top: -2px; + left: 10px; + width: 20px; + height: 20px; + cursor: pointer; +} + +div[id^=GPlayerInfoClose] { + position: absolute; + top: -8px; + right: 10px; + width: 28px; + height: 28px; + cursor: pointer; +} + +div[id^=GPlayerInfoDescription] { + font-size: 0.9em; +} + +div[id^=GPlayerInfoLegend] { + +} + +div[id^=GPlayerInfoMetadata] { + +} + +.GPlayerInfoSubtitle { + padding-left: 35px; + font-weight: bold; + margin-top: 10px; + margin-bottom: 4px; +} + +.GPlayerInfoLink, +.GPlayerInfoPopup { + line-height: 20px; + padding-left: 23px; + white-space: nowrap; + overflow-x: hidden; + text-overflow: ellipsis; + color: #999999; + background-repeat: no-repeat; + cursor: pointer; +} + +.GPlayerInfoLink { + background-position: 0 -20px; +} + +.GPlayerInfoLink:hover, +.GPlayerInfoPopup:hover { + color: #333; +} + +.GPlayerInfoLink a, +.GPlayerInfoLink a:visited +.GPlayerInfoLink a:focus +.GPlayerInfoLink a:hover { + text-decoration: none; + color: inherit; +} diff --git a/src/Common-review/CSS/GPlocation.css b/src/Common-review/CSS/GPlocation.css new file mode 100644 index 000000000..0db15e710 --- /dev/null +++ b/src/Common-review/CSS/GPlocation.css @@ -0,0 +1,52 @@ +/* Location */ + +/* Location form */ + +.GPlocationStageFlexInput { + max-height: 28px; + opacity: 1; +} + +.GPlocationStageFlexInputHidden { + max-height: 0; + opacity: 0; + overflow: hidden; +} + +.GPlocationOriginVisible { + display: block; +} + +.GPlocationOriginHidden { + display: none; +} + +label.GPlocationOriginPointerImg[id*="GPlocationOriginPointerImg"] { + width: 28px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + border-right: 1px solid #999; +} + +input[id*="GPlocationOriginPointer"] + .GPlocationOriginPointerImg { + background-position: -1px -1px; +} + +input[id*="GPlocationOriginPointer"]:checked + .GPlocationOriginPointerImg { + background-position: -29px -1px; +} + +.GPlocationStageRemove, +div[id^=GPlocationStageAdd] { + width: 28px; + border: none; + cursor: pointer; +} + +.GPlocationStageRemove { + background-position: -84px 0; +} + +div[id^=GPlocationStageAdd] { + background-position: -56px 0; +} diff --git a/src/Common-review/CSS/GPmeasureArea.css b/src/Common-review/CSS/GPmeasureArea.css new file mode 100644 index 000000000..b405a9ac7 --- /dev/null +++ b/src/Common-review/CSS/GPmeasureArea.css @@ -0,0 +1,22 @@ +/* Showing/hiding drawing panel */ + +label[id^=GPshowMeasureAreaPicto-] { + display: inline-block; +} + +input[id^=GPshowMeasureArea-] + label { + display: block; +} + +input[id^=GPshowMeasureArea-]:checked + label { + display: block; + background-color: rgba(0,60,136,0.5); +} + +input[id^=GPshowMeasureArea-] + label + div { + display: block; +} + +input[id^=GPshowMeasureArea-]:checked + label + div { + display: block; +} diff --git a/src/Common-review/CSS/GPmeasureAzimuth.css b/src/Common-review/CSS/GPmeasureAzimuth.css new file mode 100644 index 000000000..ac9a4b93d --- /dev/null +++ b/src/Common-review/CSS/GPmeasureAzimuth.css @@ -0,0 +1,22 @@ +/* Showing/hiding drawing panel */ + +label[id^=GPshowMeasureAzimuthPicto-] { + display: inline-block; +} + +input[id^=GPshowMeasureAzimuth-] + label { + display: block; +} + +input[id^=GPshowMeasureAzimuth-]:checked + label { + display: block; + background-color: rgba(0,60,136,0.5); +} + +input[id^=GPshowMeasureAzimuth-] + label + div { + display: block; +} + +input[id^=GPshowMeasureAzimuth-]:checked + label + div { + display: block; +} diff --git a/src/Common-review/CSS/GPmeasureLength.css b/src/Common-review/CSS/GPmeasureLength.css new file mode 100644 index 000000000..c520239da --- /dev/null +++ b/src/Common-review/CSS/GPmeasureLength.css @@ -0,0 +1,22 @@ +/* Showing/hiding drawing panel */ + +label[id^=GPshowMeasureLengthPicto-] { + display: inline-block; +} + +input[id^=GPshowMeasureLength-] + label { + display: block; +} + +input[id^=GPshowMeasureLength-]:checked + label { + display: block; + background-color: rgba(0,60,136,0.5); +} + +input[id^=GPshowMeasureLength-] + label + div { + display: block; +} + +input[id^=GPshowMeasureLength-]:checked + label + div { + display: block; +} diff --git a/src/Common-review/CSS/GPmeasureToolTip.css b/src/Common-review/CSS/GPmeasureToolTip.css new file mode 100644 index 000000000..fb0102bfd --- /dev/null +++ b/src/Common-review/CSS/GPmeasureToolTip.css @@ -0,0 +1,46 @@ +/* MEASURE TOOL */ + +.GPmeasureTooltip { + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: 4px; + color: white; + padding: 4px 8px; + white-space: nowrap; +} + +.GPmeasureTooltip-measure { + font-weight: bold; +} + +.GPmeasureTooltip-info { + font-size: 0.75em; + text-align: center; +} + +.GPmeasureTooltip-static { + background-color: #ffcc33; + color: black; + border: 1px solid white; +} + +.GPmeasureTooltip-hidden { + display: none; +} + +.GPmeasureTooltip-measure::before, +.GPmeasureTooltip-info::before, +.GPmeasureTooltip-static::before { + border-top: 6px solid rgba(0, 0, 0, 0.5); + border-right: 6px solid transparent; + border-left: 6px solid transparent; + content: ""; + position: absolute; + bottom: -6px; + margin-left: -7px; + left: 50%; +} + +.GPmeasureTooltip-static::before { + border-top-color: #ffcc33; +} diff --git a/src/Common-review/CSS/GPmousePosition.css b/src/Common-review/CSS/GPmousePosition.css new file mode 100644 index 000000000..6ce642695 --- /dev/null +++ b/src/Common-review/CSS/GPmousePosition.css @@ -0,0 +1,215 @@ +/* MOUSE POSITION */ + +/* Showing/hiding mouse position panel */ + +label[id^=GPshowMousePositionPicto] { + display: inline-block; +} + +input[id^=GPshowMousePosition-] + label { + display: block; +} + +input[id^=GPshowMousePosition-]:checked + label { + display: none; +} + +input[id^=GPshowMousePosition-] + label + div { + display: none; +} + +input[id^=GPshowMousePosition-]:checked + label + div { + display: block; +} + +/* General panels */ + +div[id^=GPmousePositionPanel-] { + width: 300px; + overflow: hidden; +} + +/* Basic infos */ + +div[id^=GPmousePositionBasicPanel] { + padding: 10px 15px; + position: relative; +} + +.GPmousePositionLabel, +.GPmousePositionCoords { + display: inline-block; + line-height: 20px; +} + +.GPmousePositionLabel { + width: 80px; + font-weight: bold; +} + +.GPmousePositionCoords { + width: 110px; +} + +/* Showing settings */ + +.GPshowMousePositionSettingsPicto { + bottom: 5px; + right: 0; + transition: all 0.5s ease-out 0s; +} + +div[id^=GPmousePosition-] input[type="checkbox"]:checked + .GPshowMousePositionSettingsPicto { + bottom: 100px; +} + +div[id^=GPmousePositionSettings-] { + display: block; + max-height: 0; + opacity: 0; + transition: max-height 0.5s ease-out 0s, opacity 0.5s ease-out 0s; +} + +div[id^=GPmousePosition-] input[type="checkbox"]:checked + label + div[id^=GPmousePositionSettings-] { + max-height: 95px; + opacity: 1; +} + +/* Settings */ + +div[id^=GPmousePositionSettings-] { + height: 95px; + padding-left: 0 15px; + overflow: hidden; +} + +.GPmousePositionSettingsLabel { + display: block; + margin: auto; + text-align: center; + font-weight: bold; + line-height: 16px; +} + +.GPmousePositionSettingsSelect { + width: 180px; + margin-top: 5px; +} + +/* General panels */ + +div[id^=GPmousePositionCoordinate-] input.error { + border: 1px solid rgb(255, 0, 0); +} +div[id^=GPmousePositionCoordinate-] input[readonly] { + border: 1px solid transparent; + padding: 2px; + text-align: right; +} + +input[id^=GPmousePositionLat-], input[id^=GPmousePositionLon-] { + width: 120px; +} + +span[id^=GPmousePositionAlt-] { + display: inline-block; + padding: 2px; + width: 120px; + line-height: 20px; + text-align: right; +} + +/* sexagesimal coordinates */ + +.GPSexagesimal, .GPSexagesimalsec { + margin:0; + border: 1px solid rgb(204, 204, 204); + border-radius: 4px; +} + +input:read-only.GPSexagesimal, input:read-only.GPSexagesimalsec { + text-align: right; +} + +.GPSexagesimal { + width: 30px; +} + +.GPSexagesimalsec { + width: 45px; +} +.GPmousePositionSexagesimalLabel { + font-size: 1.2em; + vertical-align: middle; + padding: 0; +} + +/* direction N/S ou E/O */ +select.GPmousePositionDirection { + border: 1px solid #999; + margin-left: 2px; +} + +select.GPmousePositionDirection:disabled{ + border: none; + background: transparent; + color: black; + /*For FireFox*/ + -webkit-appearance: none; + /*For Chrome*/ + -moz-appearance: none; +} + +/*For IE10+*/ +select.GPmousePositionDirection:disabled::-ms-expand { + display: none; +} +select.GPmousePositionDirection:disabled::-ms-value { + color: black; +} + +.GPmousePositionUnits, +.GPmousePositionAltitudeUnits { + margin-left: 5px; +} + +/* EDIT COORDINATES TOOLS */ +.GPmousePositionPanelEditTools { + position: absolute; + top: 20px; + right: 5px; +} + +.GPmousePositionEditTool { + width: 18px; + height: 18px; + display: inline-block; + cursor: pointer; +} + +span[id^=GPmousePositionCloseEdit] { + background-position: -18px 0; + margin-left: 5px; +} + +img[id^=GPmousePositionMarker]:hover { + cursor: pointer; + opacity: 0.7; +} + +/* Map center localisation */ + +#GPmapCenter { + display: none; + position: absolute; + top: 50%; + left: 50%; + width: 50px; + height: 50px; + margin-top: -25px; + margin-left: -25px; +} + +#GPmapCenter.GPmapCenterVisible { + display: block; +} diff --git a/src/Common-review/CSS/GPreverseGeocoding.css b/src/Common-review/CSS/GPreverseGeocoding.css new file mode 100644 index 000000000..458011970 --- /dev/null +++ b/src/Common-review/CSS/GPreverseGeocoding.css @@ -0,0 +1,161 @@ +/* REVERSE GEOCODING */ + +[id^="GPreverseGeocoding-"] { + top: 180px; +} + +/* Showing/hiding reverse geocoding panel */ + +[id^="GPshowReverseGeocodingPicto-"] { + display: inline-block; +} + +[id^="GPshowReverseGeocoding-"] + label { + display: block; +} + +[id^="GPshowReverseGeocoding-"]:checked + label { + display: none; +} + +[id^="GPshowReverseGeocoding-"] + label + div { + display: none; +} + +[id^="GPshowReverseGeocoding-"]:checked + label + div { + display: block; +} + +/* General panels */ + +div[id^=GPreverseGeocodingResultsClose] { + top: 0; + right: 0; + width: 30px; + height: 32px; + /*background-position: -26px 0;*/ +} + +[id^="GPreverseGeocodingPanel-"] { + width: 280px; +} + +.GPreverseGeocodingComponentHidden { + display: none; +} + +div[id^="GPreverseGeocodingReturnPicto-"] { + position: absolute; + width: 26px; + height: 26px; + border-radius: 3px; + opacity: 1; + background-position: 0 0; + cursor: pointer; +} + +.GPreverseGeocodingReturnPictoHidden { + display: none; +} + +/* Calc waiting */ + +.GPreverseGeocodingCalcWaitingContainerVisible, +.GPreverseGeocodingCalcWaitingContainerHidden { + position: absolute; + top: 32px; + bottom: 0; + left: 0; + right: 0; + background-color: rgba(255,255,255,0.9); + font-size: 1.5em; + font-weight: bold; + overflow: hidden; +} + +.GPreverseGeocodingCalcWaitingContainerVisible { + display: -webkit-flex; + display: -ms-flexbox; + display: -webkit-box; + display: flex; +} + +.GPreverseGeocodingCalcWaitingContainerHidden { + display: none; +} + +.GPreverseGeocodingCalcWaiting { + margin: auto; +} + +/* Search panel */ + +[id^="GPreverseGeocodingForm-"] { + position: relative; + max-height: 270px; + overflow-y: auto; + padding-left: 15px; + padding-right: 15px; + padding-top: 10px; +} + +.GPreverseGeocodingCodeLabel, +.GPreverseGeocodingFilterLabel { + max-width: 105px; +} + +.GPreverseGeocodingCodeLabel, +.GPreverseGeocodingCode { + margin-top: 5px; + margin-bottom: 0; +} + +.GPreverseGeocodingFilterLabel, +.GPreverseGeocodingFilterInput { + margin-bottom: 5px; +} + +input[id^="GPreverseGeocodingSubmit-"] { + margin-top: 5px; + margin-bottom: 15px; + width: 100px; +} + +/* Calc waiting */ + +/* TODO: waiting */ +.GPreverseGeocodingCalcWaitingContainerVisible, +.GPreverseGeocodingCalcWaitingContainerHidden { + position: absolute; + top: 32px; + bottom: 0; + left: 0; + right: 0; + background-color: rgba(255,255,255,0.9); + font-size: 1.5em; + font-weight: bold; + overflow: hidden; +} + +.GPreverseGeocodingCalcWaitingContainerVisible { + display: -webkit-flex; + display: -ms-flexbox; + display: -webkit-box; + display: flex; +} + +.GPreverseGeocodingCalcWaitingContainerHidden { + display: none; +} + +.GPreverseGeocodingCalcWaiting { + margin: auto; +} + +/* Result panel */ + +div[id^=GPreverseGeocodingResultsList-] { + position: relative; + max-height: 210px; + overflow-y: auto; +} diff --git a/src/Common-review/CSS/GProute.css b/src/Common-review/CSS/GProute.css new file mode 100644 index 000000000..00768097a --- /dev/null +++ b/src/Common-review/CSS/GProute.css @@ -0,0 +1,446 @@ +/* ROUTE */ + +div[id^=GProute-] { + top: 100px; +} + +/* Showing/hiding route panel */ + +label[id^=GPshowRoutePicto] { + display: inline-block; +} + +input[id^=GPshowRoute-] + label { + display: block; +} + +input[id^=GPshowRoute-]:checked + label { + display: none; +} + +input[id^=GPshowRoute-] + label + div { + display: none; +} + +input[id^=GPshowRoute-]:checked + label + div { + display: block; +} + +/* General panels */ + +div[id^=GProutePanel-] { + width: 320px; +} + +.GProuteComponentHidden { + display: none; +} + +/* Calc waiting */ + +.GProuteCalcWaitingContainerVisible, +.GProuteCalcWaitingContainerHidden { + position: absolute; + top: 32px; + bottom: 0; + left: 0; + right: 0; + background-color: rgba(255,255,255,0.9); + font-size: 1.5em; + font-weight: bold; + overflow: hidden; +} + +.GProuteCalcWaitingContainerVisible { + display: -webkit-flex; + display: -ms-flexbox; + display: -webkit-box; + display: flex; +} + +.GProuteCalcWaitingContainerHidden { + display: none; +} + +.GProuteCalcWaiting { + margin: auto; +} + +/* Route form */ + +form[id^=GProuteForm] { + padding: 15px; +} + +.GProuteFormMini { + max-height: 58px; + overflow: hidden; + -webkit-transform: translateY(-5px); + transform: translateY(-5px); +} + +.GProuteStageFlexInput { + max-height: 28px; + opacity: 1; +} + +.GProuteStageFlexInputHidden { + max-height: 0; + opacity: 0; + overflow: hidden; +} + +form[id^=GProuteForm] > .GPlocationStageFlexInput { + margin-top: 5px; +} + +form[id^=GProuteForm] > .GPlocationStageFlexInputHidden { + margin-top: 0; +} + +form[id^=GProuteForm].GProuteFormMini .GPlocationStageFlexInput:first-child { + margin-top: 5px; +} + +.GProuteOriginVisible { + display: block; +} + +.GProuteOriginHidden { + display: none; +} + +label.GProuteOriginPointerImg[id*="GProuteOriginPointerImg"] { + width: 28px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + border-right: 1px solid #999; +} + +input[id*="GProuteOriginPointer"] + .GProuteOriginPointerImg { + background-position: -1px -1px; +} + +input[id*="GProuteOriginPointer"]:checked + .GProuteOriginPointerImg { + background-position: -29px -1px; +} + +.GProuteStageRemove, +div[id^=GProuteStageAdd] { + width: 28px; + border: none; + cursor: pointer; +} + +.GProuteFormMini .GProuteStageRemove, +.GProuteFormMini div[id^=GProuteStageAdd] { + display: none; +} + +.GProuteStageRemove { + background-position: -84px 0; +} + +div[id^=GProuteStageAdd] { + background-position: -56px 0; +} + +/* Mode choice */ + +div[id^=GProuteModeChoice] { + display: -webkit-flex; + display: -ms-flexbox; + display: -webkit-box; + display: flex; + -webkit-justify-content: space-around; + -ms-flex-pack: distribute; + justify-content: space-around; + margin: 15px 0; +} + +.GProuteModeLabel { + display: block; + text-align: center; + margin-bottom: 5px; +} + +div[id^=GProuteTransportChoice] input { + display: none; +} + +.GProuteTransportImg { + display: inline-block; + width: 28px; + height: 28px; + cursor: pointer; +} + +.GProuteTransportImg:first-of-type { + margin-left: 18px; + margin-right: 10px; +} + +input[id^=GProuteTransportCar] + .GProuteTransportImg { + background-position: -112px 0; +} + +input[id^=GProuteTransportCar]:checked + .GProuteTransportImg { + background-position: -140px 0; +} + +input[id^=GProuteTransportPedestrian] + .GProuteTransportImg { + background-position: -168px 0; +} + +input[id^=GProuteTransportPedestrian]:checked + .GProuteTransportImg { + background-position: -196px 0; +} + +select[id^=GProuteComputationSelect] { + width: 100px; +} + +/* Showing/hiding exclusions */ + +input[id^=GPshowRouteExclusions] { + display: none; +} + +.GPshowRouteExclusionsPicto { + /* top: 185px; */ + /* bottom: 25px; */ + right: 0; + transition: all 0.3s ease-out 0s; +} + +input[id^=GPshowRouteExclusions] + label + div[id^=GProuteExclusions] { + max-height: 0; + opacity: 0; + margin-bottom: 0; +} + +input[id^=GPshowRouteExclusions]:checked + label + div[id^=GProuteExclusions] { + display: block; + max-height: 60px; + opacity: 1; + margin-bottom: 15px; +} + +/* Exclusions */ + +div[id^=GProuteExclusions] { + transition: max-height 0.5s ease-in-out 0.25s, opacity 0.5s ease-in-out 0.25s, margin 0.3s ease-in-out 0.25s; + overflow: hidden; +} + +.GProuteExclusionsLabel { + display: block; + text-align: center; + margin-bottom: 10px; + font-weight: bold; + line-height: 16px; +} + +.GProuteExclusionsOptions { + display: -webkit-flex; + display: -ms-flexbox; + display: -webkit-box; + display: flex; + -webkit-justify-content: space-around; + -ms-flex-pack: distribute; + justify-content: space-around; +} + +.GProuteExclusionsOption { + display: block; + height: 28px; + line-height: 26px; + color: #A77; + background-color: #FEE; + padding-left: 28px; + padding-right: 5px; + border: 1px solid #A77; + border-radius: 3px; + cursor: pointer; +} + +input:checked + .GProuteExclusionsOption { + background-color: #EFE; + background-position: 0 -28px; + color: #797; + border: 1px solid #797; +} + +/* Reset picto */ +div[id^=GProuteReset] { + position: absolute; + width: 28px; + height: 28px; + border-radius: 3px; + opacity: 0.8; + background-position: -224px 0; + transition: opacity 0.2s ease-out; + cursor: pointer; +} + +div[id^=GProuteReset]:hover { + opacity: 1; +} + +/* Result panel */ + +div[id^=GProuteResultsPanel] { + padding: 15px; +} + +.GProuteResultStage { + display: -webkit-flex; + display: -ms-flexbox; + display: -webkit-box; + display: flex; +} + +div[id^=GProuteResultsStages] { + margin-bottom: 15px; +} + +.GProuteResultStageLabel, +.GProuteResultStageValue, +.GProuteResultsValueLabel, +div[id^=GProuteResultsValueDist], +div[id^=GProuteResultsValueTime] { + display: inline-block; + line-height: 18px; +} + +.GProuteResultStageLabel, +.GProuteResultsValueLabel { + color: #666; +} + +.GProuteResultStageLabel { + width: 60px; +} + +.GProuteResultsValueLabel { + width: 65px; +} + +.GProuteResultStageValue { + -webkit-flex: 1; + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1; + overflow-x: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +div[id^=GProuteResultsValueDist], +div[id^=GProuteResultsValueTime] { + width: 80px; + font-weight: bold; +} + +div[id^=GProuteResults-] { + display: -webkit-flex; + display: -ms-flexbox; + display: -webkit-box; + display: flex; + -webkit-justify-content: space-between; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-bottom: 10px; +} + +select[id^=GProuteResultsComputationSelect] { + width: 100px; +} + +div[id^=GProuteResultsNew] { + width: 28px; + height: 28px; + border-radius: 3px; + opacity: 0.8; + background-position: -224px 0; + transition: opacity 0.2s ease-out; + cursor: pointer; +} + +div[id^=GProuteResultsNew]:hover { + opacity: 1; +} + +/* Results details header */ + +.GPfakeBorder { + display: inline-block; + height: 14px; + width: 60px; + border-bottom: 1px solid #999; +} + +.GPfakeBorderLeft { + margin-left:15px; +} + +input[id^=GProuteResultsShowDetails] + label, +input[id^=GProuteResultsShowDetails] + label + label { + width: 130px; + line-height: 28px; + vertical-align: top; + text-align: center; + font-weight: bold; + cursor: pointer; + transition: color 0.2s ease-out; +} + +input[id^=GProuteResultsShowDetails] + label, +input[id^=GProuteResultsShowDetails]:checked + label + label { + display: inline-block; +} + +input[id^=GProuteResultsShowDetails]:checked + label, +input[id^=GProuteResultsShowDetails] + label + label { + display: none; +} + +input[id^=GProuteResultsShowDetails] + label + label + div + div[id^=GProuteResultsDetails] { + max-height: 0; + opacity: 0; +} + +input[id^=GProuteResultsShowDetails]:checked + label + label + div + div[id^=GProuteResultsDetails] { + max-height: 200px; + opacity: 1; +} + +div[id^=GProuteResultsDetails] { + overflow-y: auto; + transition: max-height 0.5s ease-in-out 0.25s, opacity 0.5s ease-in-out 0.25s; +} + +.GProuteResultsDetailsNumber, +.GProuteResultsDetailsInstruction { + display: inline-block; + margin-top: 4px; + line-height: 16px; + color: #666; +} + +.GProuteResultsDetailsNumber { + font-weight: bold; + width: 22px; + text-align: right; + vertical-align: top; +} + +.GProuteResultsDetailsInstruction { + width: calc(100% - 30px); + padding-left: 5px; +} diff --git a/src/Common-review/CSS/GPsearchEngine.css b/src/Common-review/CSS/GPsearchEngine.css new file mode 100644 index 000000000..0e915f9fe --- /dev/null +++ b/src/Common-review/CSS/GPsearchEngine.css @@ -0,0 +1,175 @@ +/* SEARCH ENGINE */ + +input[id^=GPshowSearchEngine-] + label + form[id^=GPsearchInput-] { + max-width: 0px; +} + +/* Showing/hiding search engine input */ + +input[id^=GPshowSearchEngine-] { + display: none; +} + +label[id^=GPshowSearchEnginePicto] { + display: inline-block; + transition: border-radius 0s ease-out 0s; + transition-delay: 0.5s; +} + +input[id^=GPshowSearchEngine-]:checked + label { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + transition-delay: 0s; +} + +input[id^=GPshowSearchEngine-] + label + form[id^=GPsearchInput-] { + max-width: 0px; + border: none; + transition: max-width 0.5s ease-out 0s; +} + +input[id^=GPshowSearchEngine-]:checked + label + form[id^=GPsearchInput-] { + max-width: 280px; +} + +input[id^=GPshowSearchEngine-] + label + form[id^=GPsearchInput-] + div[id^=GPshowAdvancedSearch] { + display: none; +} + +input[id^=GPshowSearchEngine-]:checked + label + form[id^=GPsearchInput-] + div[id^=GPshowAdvancedSearch] { + display: inline-block; +} + +div[id^=GPautoCompleteList] { + display: none; +} + +input[id^=GPshowSearchEngine-]:checked + label + form[id^=GPsearchInput-] + div[id^=GPautoCompleteList] { + display: block; +} + +/* Simple search input */ + +form[id^=GPsearchInput-] { + display: inline-block; + position: relative; + left: -3px; + width: 280px; + overflow: hidden; +} + +form[id^=GPsearchInput-] input { + display: block; + width: 100%; + height: 100%; + border: 1px solid #999; + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; + padding: 0; + padding-right: 30px; + padding-left: 5px; + color: #333; + font-size: 1.0em; +} + +form[id^=GPsearchInput-] input:disabled { + background-color: #DDD; + color: #999; +} + +div[id^=GPsearchInputReset] { + position: absolute; + top: 0; + right: 0; + width: 30px; + height: 32px; + background-position: -30px 0; + cursor: pointer; +} + +/* General panels */ + +div[id^=GPgeocodeResultsClose], +div[id^=GPadvancedSearchClose] { + top: 0; + right: 0; + width: 30px; + height: 32px; +} + +div[id^=GPgeocodeResultsClose] { + background-position: 0 0; +} + +div[id^=GPadvancedSearchClose] { + background-repeat: no-repeat; +} + +/* Advanced search picto */ + +div[id^=GPshowAdvancedSearch] { + transition: border-radius 0s ease-out 0s; + transition-delay: 0.5s; +} + +/* Advanced search panel */ + +div[id^=GPadvancedSearchPanel] { + display: none; + width: 280px; + vertical-align: top; + overflow: hidden; +} + +form[id^=GPadvancedSearchForm] { + max-height: 220px; + overflow-y: auto; + padding-left: 15px; + padding-right: 15px; +} + +.GPadvancedSearchCodeLabel, +.GPadvancedSearchFilterLabel { + max-width: 105px; +} + +.GPadvancedSearchCodeLabel, +.GPadvancedSearchCode, + div[id^=GPadvancedSearchFilters] { + margin-top: 15px; +} + +.GPadvancedSearchFilterLabel, +.GPadvancedSearchFilterInput { + margin-bottom: 5px; +} + +input[id^=GPadvancedSearchSubmit] { + margin-top: 10px; + margin-bottom: 15px; +} + +/* Autocomplete list / geocode results */ + +div[id^=GPautoCompleteList], +div[id^=GPgeocodeResultsList] { + width: 280px; +} + +div[id^=GPautoCompleteList] { + top: 35px; +} + +div[id^=GPgeocodeResultsList] { + display: none; + position: absolute; + top: 40px; + border-radius: 4px; + overflow: hidden; +} + +div[id^=GPgeocodeResults-] { + background-color: #FFF; + max-height: 140px; + overflow-y: auto; +} diff --git a/src/Common-review/CSS/GPwaiting.css b/src/Common-review/CSS/GPwaiting.css new file mode 100644 index 000000000..ec093cb27 --- /dev/null +++ b/src/Common-review/CSS/GPwaiting.css @@ -0,0 +1,37 @@ +/** +* Map loading +* @sample +* function setMap(map) { +* var center = this._createLoadingElement(); +* map.getViewport().appendChild(center); +* center.className = ""; // invisible ! +* center.className = "GPmapLoadingVisible"; // visible ! +* } +* +* function _createLoadingElement() { +* var div = document.createElement("div"); +* div.id = "GPmapLoading"; +* div.className = ""; +* return div; +* } +*/ + +#GPmapLoading { + display: none; + position: absolute; + z-index: 50; + top: 50%; + left: 50%; + width: 50px; + height: 50px; + margin-top: -25px; + margin-left: -25px; +} + +#GPmapLoading.GPmapLoadingVisible { + display: block; +} + +#GPmapLoading { + background-image: url("img/waiting.gif"); +} diff --git a/src/Common-review/CSS/img/waiting.gif b/src/Common-review/CSS/img/waiting.gif new file mode 100644 index 000000000..c7ceaea45 Binary files /dev/null and b/src/Common-review/CSS/img/waiting.gif differ diff --git a/src/Common-review/Controls/AttributionDOM.js b/src/Common-review/Controls/AttributionDOM.js new file mode 100644 index 000000000..80f55f305 --- /dev/null +++ b/src/Common-review/Controls/AttributionDOM.js @@ -0,0 +1,96 @@ +// FIXME not use !? +var AttributionDOM = { + + // ################################################################### // + // ######################### Main container ########################## // + // ################################################################### // + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Creation du container principal (DOM) + * + * @returns {DOMElement} div DOM + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPAttribution"); + container.className = "GPwidget"; + + return container; + }, + + /** + * Creation du selecteur (caché) pour l'affichage/masquage des attributions (DOM) + * + * @returns {DOMElement} checkbox DOM + */ + _createMainAttributionsShowElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowAttributionsList"); + input.type = "checkbox"; + return input; + }, + + /** + * Création de l'élément liste des attributions (DOM) + * + * @returns {DOMElement} liste DOM + */ + _createAttributionsList : function () { + var ul = document.createElement("ul"); + ul.id = this._addUID("GPAttributionsList"); + return ul; + }, + + /** + * Création du conteneur principal des attributions (DOM) + * + * @returns {DOMElement} div DOM + */ + _createMainAttributionsListContainer : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPAttributionsListContainer"); + + return div; + }, + + /** + * Création du container du picto du controle (DOM) + * @param {Boolean} collapsed - collapsed + * @returns {DOMElement} label DOM + */ + _createMainPictoElement : function (collapsed) { + var self = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowAttributionsListPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowAttributionsList"); + label.title = "Afficher/masquer les attributions"; + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowAttributionsListOpenClose"); + spanOpen.className = "GPshowAdvancedToolOpen"; + spanOpen.innerHTML = collapsed ? "i" : "»"; + /** Evenement de type 'click' sur le picto du controle */ + spanOpen.addEventListener("click", function () { + spanOpen.innerHTML = (document.getElementById(self._addUID("GPshowAttributionsList")).checked) ? "i" : "»"; + }); + + label.appendChild(spanOpen); + + return label; + } + +}; + +export default AttributionDOM; diff --git a/src/Common-review/Controls/BoostReliefDOM.js b/src/Common-review/Controls/BoostReliefDOM.js new file mode 100644 index 000000000..6a39cf1fd --- /dev/null +++ b/src/Common-review/Controls/BoostReliefDOM.js @@ -0,0 +1,242 @@ +var BoostReliefDOM = { + + // ################################################################### // + // ######################### Main container ########################## // + // ################################################################### // + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Creation du container principal (DOM) + * + * @returns {DOMElement} container - layer switcher DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPboostRelief"); + container.className = "GPwidget"; + return container; + }, + + /** + * Creation du selecteur (caché) pour l'affichage/masquage des slides de boostRelief (DOM) + * + * @param {Boolean} collapsed - option indiquant si le control est déplié + * + * @returns {DOMElement} checkbox DOM + */ + _createMainBoostReliefShowElement : function (collapsed) { + var input = document.createElement("input"); + input.id = this._addUID("GPshowBoostReliefList"); + input.type = "checkbox"; + if (collapsed) { + input.checked = true; + } + return input; + }, + + // ################################################################### // + // ############################ Relief tool ########################### // + // ################################################################### // + + /** + * Creation du container des outils avancés du layer (DOM) + * + * @param {Object} brOptions - options du control boostRelief + * + * @returns {DOMElement} container + */ + _createAdvancedToolElement : function (brOptions) { + // exemple : + //
+ // + //
+ var container = document.createElement("div"); + container.className = "GPlayerAdvancedToolsRelief"; + + var array = this._createAdvancedToolReliefElement(brOptions.scale, brOptions.defaultBoost); + for (var j = 0; j < array.length; j++) { + container.appendChild(array[j]); + } + + return container; + }, + /** + * Creation de l'icone de gestion du relief du layer (DOM) + * + * @param {Object} scale - définition de l'echelle que le slider utilise (min,max,step) + * + * @returns {DOMElement[]} array of two containers + */ + _createAdvancedToolReliefElement : function (scale, defaultBoost) { + // exemple : + //
+ // Layer1 + //
+ // + //
+ // + //
+ //
+ // 100 + // % + //
+ + var list = []; + + // curseur pour changer l'exageration du relief + var divB = document.createElement("div"); + divB.className = "GPlayerRelief"; + divB.title = "Relief"; + + // le relief est à un facteur 1 par défaut + var relief = 1; + + var input = document.createElement("input"); + input.id = this._addUID("GPreliefValueDiv"); + input.type = "range"; + + // echelle de 1 à 50 par defaut + if (!scale) { + scale = { + min : 1, + max : 50, + step : 1 + }; + }; + + input.min = scale.min || 1; + input.max = scale.max || 50; + input.step = scale.step || 1; + + + // le relief est à un facteur 1 par défaut + var defaultBoostValue = 1; + if (defaultBoost) { + defaultBoostValue = defaultBoost; + } + + // the reliefValue given must me in the slider range + if (defaultBoostValue > input.max) { + defaultBoostValue = input.max; + } + + if (defaultBoostValue < input.min) { + defaultBoostValue = input.min; + } + + // mise à jour des couches et du slider une fois le controle ajouté + input.value = defaultBoostValue; + + // add event for relief change + var context = this; + if (input.addEventListener) { + input.addEventListener( + "change", + function (e) { + context._onChangeLayerRelief(e); + } + ); + } else if (input.attachEvent) { + // internet explorer + input.attachEvent( + "onchange", + function (e) { + context._onChangeLayerRelief(e); + } + ); + } + + if (input.addEventListener) { + input.addEventListener( + "input", + function (e) { + context._onChangeLayerRelief(e); + } + ); + } else if (input.attachEvent) { + // internet explorer + input.attachEvent( + "oninput", + function (e) { + context._onChangeLayerRelief(e); + } + ); + } + + divB.appendChild(input); + + // Valeur d'echelle du relief + var divC = document.createElement("div"); + divC.id = this._addUID("GPreliefValueDiv"); + divC.className = "GPlayerReliefValue"; + + var span = document.createElement("span"); + span.id = this._addUID("GPreliefValue"); + span.innerHTML = "x" + relief; + + divC.appendChild(span); + + list.push(divB); + list.push(divC); + + return list; + }, + + /** + * Création du conteneur principal des couches MNT boostRelief (DOM) + * + * @returns {DOMElement} div DOM + */ + _createMainBoostReliefListContainer : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPBoostReliefListContainer"); + div.className = "GPpanel"; + + return div; + }, + + /** + * Show boostRelief control + * @param {Boolean} isDesktop - specifies if the support is desktop or tactile + * + * @returns {DOMElement} DOM element + */ + + _createMainPictoElement : function () { + var self = this; + var label = document.createElement("label"); + + label.id = this._addUID("GPshowBoostReliefListPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowBoostReliefList"); + label.title = "Afficher/Masquer le control d'exageration du relief"; + + var spanOpenClose = document.createElement("span"); + spanOpenClose.id = this._addUID("GPshowBoostReliefOpenClose"); + spanOpenClose.className = "GPshowAdvancedToolOpen"; + + /** Evenement de type 'click' sur le picto du controle */ + label.addEventListener("click", function () { + if (document.getElementById(self._addUID("GPshowBoostReliefList")).checked) { + document.getElementById(self._addUID("GPBoostReliefListContainer")).style.display = "none"; + } else { + document.getElementById(self._addUID("GPBoostReliefListContainer")).style.display = "block"; + } + }); + + label.appendChild(spanOpenClose); + + return label; + } +}; + +export default BoostReliefDOM; diff --git a/src/Common-review/Controls/DrawingDOM.js b/src/Common-review/Controls/DrawingDOM.js new file mode 100644 index 000000000..0db76f948 --- /dev/null +++ b/src/Common-review/Controls/DrawingDOM.js @@ -0,0 +1,671 @@ +import Logger from "../../Common/Utils/LoggerByDefault"; + +var logger = Logger.getLogger("DrawingDOM"); + +var DrawingDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPdrawing"); + container.className = "GPwidget"; + return container; + }, + + // ################################################################### // + // ################### Methods of main container ##################### // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing + * + * @returns {DOMElement} DOM element + */ + _createShowDrawingElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowDrawing"); + input.className = "GPshowDrawing"; + input.type = "checkbox"; + return input; + }, + + /** + * Show mouse position control + * + * @returns {DOMElement} DOM element + */ + _createShowDrawingPictoElement : function () { + var self = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowDrawingPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowDrawing"); + label.title = this.options.labels.control; + + // gestionnaire d'evenement : + // on ouvre le menu de saisie de saisie + // L'ouverture/Fermeture permet de faire le menage + // (reinitialisation) + if (label.addEventListener) { + label.addEventListener("click", function (e) { + self.onShowDrawingClick(e); + }); + } else if (label.attachEvent) { + label.attachEvent("onclick", function (e) { + self.onShowDrawingClick(e); + }); + } + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowDrawingOpen"); + spanOpen.className = "GPshowAdvancedToolOpen"; + label.appendChild(spanOpen); + + return label; + }, + + /** + * Drawing panel + * + * @returns {DOMElement} DOM element + */ + _createDrawingPanelElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPdrawingPanel"); + div.className = "GPpanel"; + + return div; + }, + + // ################################################################### // + // ####################### Panel container ########################### // + // ################################################################### // + + /** + * Creates drawing Panel header DOM structure + * @returns {DOMElement} DOM element + */ + _createDrawingPanelHeaderElement : function () { + /* + *
+ *
Annoter la carte
+ *
+ *
+ */ + + var container = document.createElement("div"); + container.className = "GPpanelHeader"; + + var divTitle = document.createElement("div"); + divTitle.className = "GPpanelTitle"; + divTitle.innerHTML = this.options.controlLabel || "Annoter la carte"; + container.appendChild(divTitle); + + var divClose = document.createElement("div"); + divClose.id = this._addUID("GPdrawingPanelClose"); + divClose.className = "GPpanelClose"; + divClose.title = "Fermer le panneau"; + + // Link panel close / visibility checkbox + var dtObj = this; + if (divClose.addEventListener) { + divClose.addEventListener("click", function () { + document.getElementById(dtObj._addUID("GPshowDrawingPicto")).click(); + }, false); + } else if (divClose.attachEvent) { + divClose.attachEvent("onclick", function () { + document.getElementById(dtObj._addUID("GPshowDrawingPicto")).click(); + }); + } + + container.appendChild(divClose); + + return container; + }, + + /** + * Creates drawing tools section. + * + * @returns {DOMElement} DOM element + */ + _createDrawingToolsSections : function () { + var tools = []; + + this.dtOptions = {}; + if (this.options.tools.points) { + this.dtOptions.points = { + label : this.options.labels.points, + active : false, + panel : "draw", + id : "point" + }; + } + if (this.options.tools.lines) { + this.dtOptions.lines = { + label : this.options.labels.lines, + active : false, + panel : "draw", + id : "line" + }; + } + if (this.options.tools.polygons) { + this.dtOptions.polygons = { + label : this.options.labels.polygons, + active : false, + panel : "draw", + id : "polygon" + }; + } + if (this.options.tools.holes) { + this.dtOptions.holes = { + label : this.options.labels.holes, + active : false, + panel : "draw", + id : "holes" + }; + } + if (this.options.tools.text) { + this.dtOptions.text = { + label : this.options.labels.text, + active : false, + panel : "draw", + id : "text" + }; + } + if (this.options.tools.edit) { + this.dtOptions.edit = { + label : this.options.labels.edit, + active : false, + panel : "edit", + id : "edit" + }; + } + if (this.options.tools.display) { + this.dtOptions.display = { + label : this.options.labels.display, + active : false, + panel : "edit", + id : "display" + }; + } + if (this.options.tools.tooltip) { + this.dtOptions.tooltip = { + label : this.options.labels.tooltip, + active : false, + panel : "edit", + id : "tooltip" + }; + } + if (this.options.tools.remove) { + this.dtOptions.remove = { + label : this.options.labels.remove, + active : false, + panel : "edit", + id : "remove" + }; + } + // ajout drawing tools + if (this.dtOptions.points || + this.dtOptions.lines || + this.dtOptions.polygons || + this.dtOptions.text) { + tools.push(this._createDrawingToolSection(this.options.labels.creatingTools, "draw")); + } + // ajout editing tools + if (this.dtOptions.edit || + this.dtOptions.display || + this.dtOptions.tooltip || + this.dtOptions.remove) { + tools.push(this._createDrawingToolSection(this.options.labels.editingTools, "edit")); + } + // ajout export tools + if (this.options.tools.export) { + tools.push(this._createSavingSection( + this.options.labels.export, + this.options.labels.exportTitle + )); + } + + return tools; + }, + + /** + * Creates drawing tool section DOM structure. + * + * @param {String} sectionLabel - section title + * @param {String} panelType - Drawing ("draw") or editing ("edit") tools panel + * @returns {DOMElement} DOM element + */ + _createDrawingToolSection : function (sectionLabel, panelType) { + /* + * Exemple panelType == "draw" + * + *
+ *

Outils de création

+ * + *
+ */ + var container = document.createElement("div"); + container.className = "drawing-tool-section"; + + var p = document.createElement("p"); + p.className = "drawing-tool-section-title"; + p.innerHTML = sectionLabel; + container.appendChild(p); + + var ul = document.createElement("ul"); + ul.className = "drawing-tools-flex-display"; + var context = this; + // li click handler function + function liClickHandler (e) { + /* jshint validthis: true */ + // this == elem clicked + context._handleDOMToolClick(e, this.id, context); + context._handleToolClick(e, this.id, context); + } + for (var type in this.dtOptions) { + if (this.dtOptions[type].panel !== panelType) { + continue; + } + var li = document.createElement("li"); + li.className = "drawing-tool"; + li.id = this._addUID("drawing-tool-" + this.dtOptions[type].id); + li.title = this.dtOptions[type].label; + li.addEventListener("click", liClickHandler); + ul.appendChild(li); + } + container.appendChild(ul); + + return container; + }, + + /** + * Creates drawing tool section DOM structure. + * + * @param {String} buttonLabel - Button label + * @param {String} buttonTitle - Button title + * @returns {DOMElement} DOM element + */ + _createSavingSection : function (buttonLabel, buttonTitle) { + /* + *
+ * + *
+ */ + var container = document.createElement("div"); + container.className = "drawing-tool-section drawing-tools-flex-display"; + + var button = document.createElement("button"); + button.title = buttonTitle; + button.className = "tool-form-submit drawing-button"; + button.id = this._addUID("drawing-export"); + button.type = "button"; + button.textContent = buttonLabel; + var context = this; + /** export function */ + button.onclick = function () { + context.onExportFeatureClick(); + }; + container.appendChild(button); + + return container; + }, + + /** + * Creates input for color choosing + * + * @param {Object} options - options + * @param {String} options.defaultValue - defaultValue + * @param {String} options.className - input className + * @returns {DOMElement} - created li element + */ + _createMarkersChooser : function (options) { + var li = document.createElement("li"); + li.className = options.className; + for (var i = 0; i < this.options.markersList.length; i++) { + // radio bouton pour la selection + var inputElem = document.createElement("input"); + inputElem.type = "radio"; + inputElem.name = "marker"; + inputElem.id = this._addUID("marker-" + i); + inputElem.value = this.options.markersList[i].src; + inputElem.className = "marker-input-radio"; + if (options.defaultValue === inputElem.value) { + inputElem.checked = true; + } + li.appendChild(inputElem); + // label pour l'affichage du marker + var labelElem = document.createElement("label"); + labelElem.className = "marker-label"; // utile ? + labelElem.setAttribute("for", inputElem.id); + var imgElem = document.createElement("img"); + imgElem.src = inputElem.value; + labelElem.appendChild(imgElem); + li.appendChild(labelElem); + } + return li; + }, + + /** + * Creates input for color choosing + * + * @param {Object} options - options + * @param {String} options.label - label + * @param {String} options.type - input type for element ("color") + * @param {String} options.defaultValue - defaultValue + * @param {String} options.id - input id + * @param {String} options.title - input title + * @param {String} options.className - input className + * @returns {DOMElement} - created li element + */ + _createStylingElement : function (options) { + var li = document.createElement("li"); + li.className = options.className; + var textNode = document.createTextNode(options.label); + li.appendChild(textNode); + var inputElem = document.createElement("input"); + try { + inputElem.type = options.type; + } catch (e) { + // ie 11 input type== color ne marche pas... + inputElem.type = "text"; + } + inputElem.id = options.id; + inputElem.value = options.defaultValue; + if (options.title) { + inputElem.title = options.title; + } + // si options.type == "range" + if (options.min !== undefined) { + inputElem.min = options.min; + } + if (options.max !== undefined) { + inputElem.max = options.max; + } + if (options.step !== undefined) { + inputElem.step = options.step; + } + li.appendChild(inputElem); + return li; + }, + + /** + * Creates Styling div to include in popup. + * + * @param {Object} options - toolId selected + * @param {String} options.geomType - gemeotryType selected ("Point", "Line" or "Polygon") + * @param {Object} options.initValues - values to init fields + * @param {String} options.initValues.markerSrc - marker URL for Points + * @param {Function} options.applyFunc - function called when apply is selected + * @returns {DOMElement} DOM element created + */ + _createStylingDiv : function (options) { + var div = document.createElement("div"); + div.className = "gp-styling-div"; + var ul = document.createElement("ul"); + var li = null; + /* + * TODO : finir de remplir la div pour tous les styles éditables. + */ + switch (options.geomType.toLowerCase()) { + case "point": + li = this._createMarkersChooser({ + className : "gp-styling-option", + // defaultValue : this.options.markersList[0].src + defaultValue : options.initValues.markerSrc + }); + ul.appendChild(li); + break; + case "text": + li = this._createStylingElement({ + type : "color", + className : "gp-styling-option", + label : this.options.labels.fillColor, + id : this._addUID("fillColor"), + defaultValue : options.initValues.fillColor + }); + ul.appendChild(li); + li = this._createStylingElement({ + type : "color", + className : "gp-styling-option", + label : this.options.labels.strokeColor, + id : this._addUID("strokeColor"), + defaultValue : options.initValues.strokeColor + }); + ul.appendChild(li); + break; + case "line": + li = this._createStylingElement({ + type : "color", + className : "gp-styling-option", + label : this.options.labels.strokeColor, + id : this._addUID("strokeColor"), + defaultValue : options.initValues.strokeColor + }); + ul.appendChild(li); + li = this._createStylingElement({ + type : "range", + className : "gp-styling-option", + label : this.options.labels.strokeWidth, + title : "1 à 10 pixels", + id : this._addUID("strokeWidth"), + min : 1, + max : 10, + step : 1, + defaultValue : options.initValues.strokeWidth + }); + ul.appendChild(li); + break; + case "polygon": + li = this._createStylingElement({ + type : "color", + className : "gp-styling-option", + label : this.options.labels.strokeColor, + id : this._addUID("strokeColor"), + defaultValue : options.initValues.strokeColor + }); + ul.appendChild(li); + li = this._createStylingElement({ + type : "range", + className : "gp-styling-option", + label : this.options.labels.strokeWidth, + title : "1 à 10 pixels", + id : this._addUID("strokeWidth"), + min : 1, + max : 10, + step : 1, + defaultValue : options.initValues.strokeWidth + }); + ul.appendChild(li); + li = this._createStylingElement({ + type : "color", + className : "gp-styling-option", + label : this.options.labels.fillColor, + id : this._addUID("fillColor"), + defaultValue : options.initValues.fillColor + }); + ul.appendChild(li); + li = this._createStylingElement({ + type : "range", + className : "gp-styling-option", + label : this.options.labels.fillOpacity, + title : "0 (transparent) à 100% (opaque)", + id : this._addUID("fillOpacity"), + min : 0, + max : 10, + step : 1, + defaultValue : options.initValues.fillOpacity * 10 + }); + ul.appendChild(li); + break; + default: + logger.log("Unhandled geometry type for styling."); + } + div.appendChild(ul); + // apply button + var applyButton = document.createElement("input"); + applyButton.type = "button"; + applyButton.className = "gp-styling-button"; + applyButton.value = this.options.labels.applyToObject; + /** click sur applyButton */ + applyButton.onclick = function () { + options.applyFunc.call(this, "apply"); + }; + div.appendChild(applyButton); + // set default button + var setDefaultButton = document.createElement("input"); + setDefaultButton.type = "button"; + setDefaultButton.value = this.options.labels.setAsDefault; + setDefaultButton.className = "gp-styling-button"; + /** click sur set Default Button */ + setDefaultButton.onclick = function () { + options.applyFunc.call(this, "default"); + }; + div.appendChild(setDefaultButton); + // cancel Button + var cancelButton = document.createElement("input"); + cancelButton.type = "button"; + // cancelButton.value = "X" ; + cancelButton.className = "gp-styling-button closer"; + /** click sur cancel Button */ + cancelButton.onclick = function () { + options.applyFunc.call(this, "cancel"); + }; + div.appendChild(cancelButton); + return div; + }, + + /** + * Creates Text editing div to include in popup. + * + * @param {Object} options - options for popup + * @param {String} options.geomType - gemeotryType selected ("Point", "Line" or "Polygon") + * @param {String} options.text - text to fill input. + * @param {String} options.measure - measure to fill input. + * @param {String} options.placeholder - placeholder for text input. + * @param {String} options.inputId - text input id. + * @param {Function} options.applyFunc - function called when text is to be saved. + * @returns {DOMElement} DOM element created + * @private + */ + _createLabelDiv : function (options) { + var popup = document.createElement("div"); + popup.className = "gp-label-div"; + var inputLabel = null; + if (options.geomType === "Text") { + inputLabel = document.createElement("input"); + inputLabel.type = "text"; + inputLabel.className = "gp-input-label-style"; + } else { + inputLabel = document.createElement("textArea"); + inputLabel.rows = 2; + inputLabel.cols = 40; + inputLabel.className = "gp-textarea-att-label-style"; + } + + if (options.text) { + inputLabel.value = options.text; + } + + inputLabel.autocomplete = "off"; + inputLabel.placeholder = options.placeholder; + inputLabel.id = options.inputId; + popup.appendChild(inputLabel); + // blur + inputLabel.onblur = function () { + options.applyFunc.call(this, inputLabel.value, true); + }; + // keyup + inputLabel.onkeyup = function (evtk) { + if (options.geomType === "Text" && evtk.keyCode === 13) { + options.applyFunc.call(this, inputLabel.value, true); + } + if (evtk.keyCode === 27) { + options.applyFunc.call(this, inputLabel.value, false); + } + }; + + if (options.measure && options.geomType !== "Text") { + var inputMeasure = document.createElement("input"); + inputMeasure.type = "text"; + inputMeasure.readonly = true; + inputMeasure.className = "gp-input-measure-style"; + inputMeasure.value = options.measure; + popup.appendChild(inputMeasure); + } + + if (options.geomType !== "Text") { + // apply button + var applyButton = document.createElement("input"); + applyButton.type = "button"; + applyButton.className = "gp-styling-button"; + applyButton.value = this.options.labels.saveDescription; + /** click sur applyButton */ + applyButton.onclick = function () { + options.applyFunc.call(this, inputLabel.value, true); + }; + popup.appendChild(applyButton); + // cancel Button + var cancelButton = document.createElement("input"); + cancelButton.type = "button"; + cancelButton.className = "gp-styling-button closer"; + /** click sur cancel Button */ + cancelButton.onclick = function () { + options.applyFunc.call(this, inputLabel.value, false); + }; + popup.appendChild(cancelButton); + } + + return popup; + }, + + /** + * Handles drawing tool selection from a DOM point of view. + * + * @param {Event} e - DOM Event + * @param {String} toolId - toolId selected + * @param {DrawingDOM} context - Drawing control instance + */ + _handleDOMToolClick : function (e, toolId, context) { + for (var availType in context.dtOptions) { + var availToolId = context._addUID("drawing-tool-" + context.dtOptions[availType].id); + var li = document.getElementById(availToolId); + // ce n'est pas l'outil selectionne : on le desactive (s'il ne l'était pas déjà). + if (availToolId !== toolId) { + li.className = "drawing-tool"; + context.dtOptions[availType].active = false; + continue; + } + // ici, c'est le l'outil selectionne + if (context.dtOptions[availType].active) { + li.className = "drawing-tool"; + } else { + li.className = "drawing-tool drawing-tool-active"; + } + context.dtOptions[availType].active = !context.dtOptions[availType].active; + } + } + +}; + +export default DrawingDOM; diff --git a/src/Common-review/Controls/Editor/.gitkeep b/src/Common-review/Controls/Editor/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/src/Common-review/Controls/Editor/EditorDOM.js b/src/Common-review/Controls/Editor/EditorDOM.js new file mode 100644 index 000000000..3facbf4ba --- /dev/null +++ b/src/Common-review/Controls/Editor/EditorDOM.js @@ -0,0 +1,14 @@ +var EditorDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + } +}; + +export default EditorDOM; diff --git a/src/Common-review/Controls/ElevationPathDOM.js b/src/Common-review/Controls/ElevationPathDOM.js new file mode 100644 index 000000000..af28b935f --- /dev/null +++ b/src/Common-review/Controls/ElevationPathDOM.js @@ -0,0 +1,254 @@ +var ElevationPathDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPelevationPath"); + container.className = "GPwidget"; + return container; + }, + + // ################################################################### // + // ################# Methods to display Main Panel ################### // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing panel + * + * @returns {DOMElement} DOM element + */ + _createShowElevationPathElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowElevationPath"); + input.type = "checkbox"; + return input; + }, + + /** + * Show control + * see event ! + * + * @returns {DOMElement} DOM element + */ + _createShowElevationPathPictoElement : function () { + // contexte d'execution + var context = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowElevationPathPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowElevationPath"); + label.title = "Calculer un profil"; + + // gestionnaire d'evenement : + // on ouvre le menu de saisie de saisie + // L'ouverture/Fermeture permet de faire le menage + // (reinitialisation) + if (label.addEventListener) { + label.addEventListener("click", function (e) { + context.onShowElevationPathClick(e); + }); + } else if (label.attachEvent) { + label.attachEvent("onclick", function (e) { + context.onShowElevationPathClick(e); + }); + } + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowElevationPathOpen"); + spanOpen.className = "GPshowAdvancedToolOpen"; + label.appendChild(spanOpen); + + return label; + }, + + // ################################################################### // + // ######################### Methods to Panel ######################## // + // ################################################################### // + + /** + * Create Container Panel + * + * FIXME + * don't call this._createElevationPathPanelHeaderElement + * don't call this._createElevationPathPanelProfilElement + * + * @returns {DOMElement} DOM element + */ + _createElevationPathPanelElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPelevationPathPanel"); + div.className = "GPpanel"; + + // div.appendChild(this._createElevationPathPanelHeaderElement()); + // div.appendChild(this._createElevationPathPanelProfilElement()); + + return div; + }, + + /** + * Create Header Panel + * + * @returns {DOMElement} DOM element + */ + _createElevationPathPanelHeaderElement : function () { + var self = this; + + var container = document.createElement("div"); + container.className = "GPpanelHeader"; + + var divInfo = document.createElement("div"); + divInfo.id = this._addUID("GPelevationPathPanelInfo"); + divInfo.className = "GPpanelInfo"; + divInfo.title = "Informations"; + // add event on click + if (divInfo.addEventListener) { + divInfo.addEventListener( + "click", + function () { + self.onOpenElevationPathInfoClick(); + } + ); + } else if (divInfo.attachEvent) { + // internet explorer + divInfo.attachEvent( + "onclick", + function () { + self.onOpenElevationPathInfoClick(); + } + ); + } + container.appendChild(divInfo); + + var divTitle = document.createElement("div"); + divTitle.className = "GPpanelTitle"; + divTitle.innerHTML = "Profil Altimétrique"; + container.appendChild(divTitle); + + var divReduce = document.createElement("div"); + divReduce.id = this._addUID("GPelevationPathPanelReduce"); + divReduce.className = "GPpanelReduce"; + divReduce.title = "Masquer le panneau"; + + if (divReduce.addEventListener) { + divReduce.addEventListener("click", function () { + if (typeof self.onReduceElevationPathPanelClick === "function") { + document.getElementById(self._addUID("GPshowElevationPath")).checked = false; + self.onReduceElevationPathPanelClick(); + } + }, false); + } else if (divReduce.attachEvent) { + divReduce.attachEvent("onclick", function () { + if (typeof self.onReduceElevationPathPanelClick === "function") { + document.getElementById(self._addUID("GPshowElevationPath")).checked = false; + self.onReduceElevationPathPanelClick(); + } + }); + } + container.appendChild(divReduce); + + var divClose = document.createElement("div"); + divClose.id = this._addUID("GPelevationPathPanelClose"); + divClose.className = "GPpanelClose"; + divClose.title = "Fermer le panneau"; + + // Link panel close / visibility checkbox + if (divClose.addEventListener) { + divClose.addEventListener("click", function () { + document.getElementById(self._addUID("GPshowElevationPathPicto")).click(); + }, false); + } else if (divClose.attachEvent) { + divClose.attachEvent("onclick", function () { + document.getElementById(self._addUID("GPshowElevationPathPicto")).click(); + }); + } + container.appendChild(divClose); + + return container; + }, + + /** + * Create Form + * see evenement ! + * + * @returns {DOMElement} DOM element + */ + _createElevationPathPanelProfilElement : function () { + var div = document.createElement("div"); + div.id = "GPelevationPathProfil"; + + return div; + }, + + /** + * Create Waiting Panel + * + * @returns {DOMElement} DOM element + */ + _createElevationPathWaitingElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPelevationPathCalcWaitingContainer"); + div.className = "GPelevationPathCalcWaitingContainerHidden"; + + var p = document.createElement("p"); + p.className = "GPelevationPathCalcWaiting"; + p.innerHTML = "Calcul en cours..."; + + div.appendChild(p); + + return div; + }, + + /** + * Create information Panel + * + * @returns {DOMElement} DOM element + */ + _createElevationPathInformationsElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPelevationPathInformationsContainer"); + div.className = "GPelevationPathInformationsContainerHidden"; + + var p = document.createElement("p"); + p.className = "GPelevationPathInformations"; + p.innerHTML = "Aucune information..."; + div.appendChild(p); + + return div; + }, + + /** + * Add a information into Panel + * + * @param {String} value - value of item + * @returns {DOMElement} DOM element + */ + _addElevationPathInformationsItem : function (value) { + var div = document.getElementById(this._addUID("GPelevationPathInformationsContainer")); + + if (div) { + var p = document.createElement("p"); + p.className = "GPelevationPathInformations"; + p.innerHTML = value; + div.appendChild(p); + } + + return div; + } +}; + +export default ElevationPathDOM; diff --git a/src/Common-review/Controls/GetFeatureInfoDOM.js b/src/Common-review/Controls/GetFeatureInfoDOM.js new file mode 100644 index 000000000..73aac2546 --- /dev/null +++ b/src/Common-review/Controls/GetFeatureInfoDOM.js @@ -0,0 +1,77 @@ +var GetFeatureInfoDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPgetFeatureInfo"); + container.className = "GPwidget"; + return container; + }, + + // ################################################################### // + // ################# Methods to display Main Panel ################### // + // ################################################################### // + + /** + * Hidden checkbox for activating getFeatureInfo + * @param {Boolean} activate - specify if the control is active or inactive + * + * @returns {DOMElement} DOM element + */ + _createActivateGetFeatureInfoElement : function (activate) { + // contexte d'execution + var context = this; + + var input = document.createElement("input"); + input.id = this._addUID("GPactivateGetFeatureInfo"); + input.type = "checkbox"; + input.checked = activate; + + input.addEventListener("change", function (e) { + context.onActivateGetFeatureInfoElementChange(e); + }); + + return input; + }, + + /** + * Creation du container du picto du controle (DOM) + * @returns {DOMElement} DOM element + */ + _createMainPictoElement : function () { + var self = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPgetFeatureInfoPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPactivateGetFeatureInfo"); + label.title = "activer/desactiver l'interrogation des couches"; + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPgetFeatureInfoActivate"); + spanOpen.className = "GPshowAdvancedToolOpen"; + label.appendChild(spanOpen); + + var spanClose = document.createElement("span"); + spanClose.id = self._addUID("GPgetFeatureInfoDeactivate"); + label.appendChild(spanClose); + + return label; + } +}; + +export default GetFeatureInfoDOM; diff --git a/src/Common-review/Controls/IsoDOM.js b/src/Common-review/Controls/IsoDOM.js new file mode 100644 index 000000000..6deb3982b --- /dev/null +++ b/src/Common-review/Controls/IsoDOM.js @@ -0,0 +1,835 @@ +var IsoDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPisochron"); + container.className = "GPwidget"; + return container; + }, + + // ################################################################### // + // ################# Methods to display Main Panel ################### // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing panel + * + * @returns {DOMElement} DOM element + */ + _createShowIsoElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowIsochron"); + input.type = "checkbox"; + return input; + }, + + /** + * Show iso control + * see event ! + * + * @returns {DOMElement} DOM element + */ + _createShowIsoPictoElement : function () { + // contexte d'execution + var context = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowIsochronPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowIsochron"); + label.title = "Calculer une isochrone"; + + // gestionnaire d'evenement : + // on ouvre le menu de saisie du calcul d'isochrone + // L'ouverture/Fermeture permet de faire le menage + // (reinitialisation) + if (label.addEventListener) { + label.addEventListener("click", function (e) { + context.onShowIsoPanelClick(e); + }); + } else if (label.attachEvent) { + label.attachEvent("onclick", function (e) { + context.onShowIsoPanelClick(e); + }); + } + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowIsochronOpen"); + spanOpen.className = "GPshowAdvancedToolOpen"; + label.appendChild(spanOpen); + + return label; + }, + + // ################################################################### // + // ################## Methods to display Inputs Panel ################ // + // ################################################################### // + + /** + * Create Container Panel + * + * FIXME + * don't call this._createIsoPanelHeaderElement + * don't call this._createIsoPanelFormElement + * + * @returns {DOMElement} DOM element + */ + _createIsoPanelElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPisochronPanel"); + div.className = "GPpanel"; + + // div.appendChild(this._createIsoPanelHeaderElement()); + // div.appendChild(this._createIsoPanelFormElement()); + + return div; + }, + + /** + * Create Header Panel + * + * @returns {DOMElement} DOM element + */ + _createIsoPanelHeaderElement : function () { + var self = this; + + var container = document.createElement("div"); + container.className = "GPpanelHeader"; + + var div = document.createElement("div"); + div.className = "GPpanelTitle"; + div.innerHTML = "Calcul d'isochrone"; + container.appendChild(div); + + // on desactive l'impl. reduction de la fenetre + // var divReduce = document.createElement("div"); + // divReduce.id = this._addUID("GPisochronPanelReduce"); + // divReduce.className = "GPpanelReduce"; + // divReduce.title = "Masquer le panneau"; + // + // if (divReduce.addEventListener) { + // divReduce.addEventListener("click", function () { + // if ( typeof self.onReduceIsoPanelClick === "function") { + // document.getElementById(self._addUID("GPshowIsochron")).checked = false; + // self.onReduceIsoPanelClick(); + // } + // }, false); + // } else if (divReduce.attachEvent) { + // divReduce.attachEvent("onclick", function () { + // if ( typeof self.onReduceIsoPanelClick === "function") { + // document.getElementById(self._addUID("GPshowIsochron")).checked = false; + // self.onReduceIsoPanelClick(); + // } + // }); + // } + // container.appendChild(divReduce); + + var divClose = document.createElement("div"); + divClose.id = this._addUID("GPisochronPanelClose"); + divClose.className = "GPpanelClose"; + divClose.title = "Fermer le panneau"; + + // Link panel close / visibility checkbox + if (divClose.addEventListener) { + divClose.addEventListener("click", function () { + document.getElementById(self._addUID("GPshowIsochronPicto")).click(); + }, false); + } else if (divClose.attachEvent) { + divClose.attachEvent("onclick", function () { + document.getElementById(self._addUID("GPshowIsochronPicto")).click(); + }); + } + container.appendChild(divClose); + + return container; + }, + + /** + * Create Form + * see evenement ! + * + * @returns {DOMElement} DOM element + */ + _createIsoPanelFormElement : function () { + // contexte d'execution + var self = this; + + var form = document.createElement("form"); + form.id = this._addUID("GPisochronForm"); + + form.addEventListener("submit", function (e) { + e.preventDefault(); + self.onIsoComputationSubmit(e); + return false; + }); + + return form; + }, + + /** + * Create Waiting Panel + * + * @returns {DOMElement} DOM element + */ + _createIsoWaitingElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPisochronCalcWaitingContainer"); + div.className = "GPisochronCalcWaitingContainerHidden"; + + var p = document.createElement("p"); + p.className = "GPisochronCalcWaiting"; + p.innerHTML = "Calcul en cours..."; + + div.appendChild(p); + + return div; + }, + + // ################################################################### // + // ############# Methods to the type choice into form ################ // + // ################################################################### // + + /** + * Create Container to type choice + * + * FIXME + * don't call this._createIsoPanelFormTypeChoiceChronElement + * don't call this._createIsoPanelFormTypeChoiceDistElement + * + * @returns {DOMElement} DOM element + */ + _createIsoPanelFormTypeChoiceElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPisochronChoice"); + + // div.appendChild(this._createIsoPanelFormTypeChoiceChronElement()); + // div.appendChild(this._createIsoPanelFormTypeChoiceDistElement()); + + return div; + }, + + /** + * Create Type choice Chron + * see event ! + * FIXME event not useful + * @param {Boolean} checked - checked + * @returns {DOMElement} DOM element + */ + _createIsoPanelFormTypeChoiceChronElement : function (checked) { + var self = this; + + var div = document.createElement("div"); + div.className = "GPisochronChoiceAlt"; + + var input = document.createElement("input"); + input.id = this._addUID("GPisochronChoiceAltChron"); + input.name = "GPisochronChoiceMode"; + input.type = "radio"; + input.checked = !!(checked); + if (input.addEventListener) { + input.addEventListener("change", function (e) { + document.getElementById(self._addUID("GPisochronValueChron")).className = "GPflexInput"; + document.getElementById(self._addUID("GPisochronValueDist")).className = "GPisochronValueHidden"; + self.onIsoTypeChoiceChange(e); + }, false); + } else if (input.attachEvent) { + input.attachEvent("onchange", function () { + document.getElementById(self._addUID("GPisochronValueChron")).className = "GPflexInput"; + document.getElementById(self._addUID("GPisochronValueDist")).className = "GPisochronValueHidden"; + self.onIsoTypeChoiceChange(); + }); + } + // info: Internet explorer support + input.value = "isochron"; + div.appendChild(input); + + var label = document.createElement("label"); + label.className = "GPisochronChoiceAltImg"; + label.htmlFor = this._addUID("GPisochronChoiceAltChron"); + div.appendChild(label); + + var span = document.createElement("span"); + span.id = this._addUID("GPisochronChoiceAltChronTxt"); + span.innerHTML = "isochrone"; + if (span.addEventListener) { + span.addEventListener("click", function () { + document.getElementById(self._addUID("GPisochronChoiceAltChron")).click(); + }, false); + } else if (span.attachEvent) { + span.attachEvent("onclick", function () { + document.getElementById(self._addUID("GPisochronChoiceAltChron")).click(); + }); + } + div.appendChild(span); + + return div; + }, + + /** + * Create Type choice Dist + * see event ! + * FIXME event not useful + * @param {Boolean} checked - checked + * @returns {DOMElement} DOM element + */ + _createIsoPanelFormTypeChoiceDistElement : function (checked) { + var self = this; + + var div = document.createElement("div"); + div.className = "GPisochronChoiceAlt"; + + var input = document.createElement("input"); + input.id = this._addUID("GPisochronChoiceAltDist"); + input.name = "GPisochronChoiceMode"; + input.type = "radio"; + input.checked = !!(checked); + if (input.addEventListener) { + input.addEventListener("change", function (e) { + document.getElementById(self._addUID("GPisochronValueDist")).className = "GPflexInput"; + document.getElementById(self._addUID("GPisochronValueChron")).className = "GPisochronValueHidden"; + self.onIsoTypeChoiceChange(e); + }, false); + } else if (input.attachEvent) { + input.attachEvent("onchange", function () { + document.getElementById(self._addUID("GPisochronValueDist")).className = "GPflexInput"; + document.getElementById(self._addUID("GPisochronValueChron")).className = "GPisochronValueHidden"; + self.onIsoTypeChoiceChange(); + }); + } + // info: Internet explorer support + input.value = "isodistance"; + div.appendChild(input); + + var label = document.createElement("label"); + label.className = "GPisochronChoiceAltImg"; + label.htmlFor = this._addUID("GPisochronChoiceAltDist"); + div.appendChild(label); + + var span = document.createElement("span"); + span.id = this._addUID("GPisochronChoiceAltDistTxt"); + span.innerHTML = "isodistance"; + if (span.addEventListener) { + span.addEventListener("click", function () { + document.getElementById(self._addUID("GPisochronChoiceAltDist")).click(); + }, false); + } else if (span.attachEvent) { + span.attachEvent("onclick", function () { + document.getElementById(self._addUID("GPisochronChoiceAltDist")).click(); + }); + } + div.appendChild(span); + + return div; + }, + + // ################################################################### // + // ############### Methods to the value iso into form ################ // + // ################################################################### // + + /** + * Create isochron inputs values + * see event ! + * @param {Boolean} checked - checked + * @returns {DOMElement} DOM element + */ + _createIsoPanelFormValueIsochronElement : function (checked) { + // contexte + var context = this; + + var div = document.createElement("div"); + div.id = this._addUID("GPisochronValueChron"); + div.className = (checked) ? "GPflexInput" : "GPisochronValueHidden"; + + var label = document.createElement("label"); + label.id = this._addUID("GPisochronValueChronLabel"); + label.htmlFor = this._addUID("GPisochronValueChronInput"); + label.innerHTML = "Temps"; + div.appendChild(label); + + var input1 = document.createElement("input"); + input1.id = this._addUID("GPisochronValueChronInput1"); + input1.min = "0"; + input1.step = "1"; + input1.value = "0"; + input1.type = "number"; + if (input1.addEventListener) { + input1.addEventListener("change", function (e) { + if (typeof context.onIsoValueChronTimeMinuteChange === "function") { + context.onIsoValueChronTimeHourChange(e); + } + }); + } else if (input1.attachEvent) { + input1.attachEvent("onchange", function (e) { + if (typeof context.onIsoValueChronTimeMinuteChange === "function") { + context.onIsoValueChronTimeHourChange(e); + } + }); + } + div.appendChild(input1); + + var label1 = document.createElement("label"); + label1.innerHTML = "h"; + div.appendChild(label1); + + var input2 = document.createElement("input"); + input2.id = this._addUID("GPisochronValueChronInput2"); + input2.min = "0"; + input2.max = "59"; + input2.step = "1"; + input2.value = "0"; + input2.type = "number"; + if (input2.addEventListener) { + input2.addEventListener("change", function (e) { + if (typeof context.onIsoValueChronTimeMinuteChange === "function") { + context.onIsoValueChronTimeMinuteChange(e); + } + }); + } else if (input2.attachEvent) { + input2.attachEvent("onchange", function (e) { + if (typeof context.onIsoValueChronTimeMinuteChange === "function") { + context.onIsoValueChronTimeMinuteChange(e); + } + }); + } + div.appendChild(input2); + + var label2 = document.createElement("label"); + label2.innerHTML = "min"; + div.appendChild(label2); + + return div; + }, + + /** + * Create isodistance inputs values + * see event ! + * @param {Boolean} checked - checked + * @returns {DOMElement} DOM element + */ + _createIsoPanelFormValueIsodistanceElement : function (checked) { + // contexte + var context = this; + + var div = document.createElement("div"); + div.id = this._addUID("GPisochronValueDist"); + div.className = (checked) ? "GPflexInput" : "GPisochronValueHidden"; + + var label = document.createElement("label"); + label.id = this._addUID("GPisochronValueDistLabel"); + label.htmlFor = this._addUID("GPisochronValueDistInput"); + label.innerHTML = "Distance"; + div.appendChild(label); + + var input1 = document.createElement("input"); + input1.id = this._addUID("GPisochronValueDistInput"); + input1.min = "0"; + input1.step = "any"; + input1.value = "0"; + input1.type = "number"; + if (input1.addEventListener) { + input1.addEventListener("change", function (e) { + if (typeof context.onIsoValueDistChange === "function") { + context.onIsoValueDistChange(e); + } + }); + } else if (input1.attachEvent) { + input1.attachEvent("onchange", function (e) { + if (typeof context.onIsoValueDistChange === "function") { + context.onIsoValueDistChange(e); + } + }); + } + div.appendChild(input1); + + var label1 = document.createElement("label"); + label1.innerHTML = "km"; + div.appendChild(label1); + + return div; + }, + + // ################################################################### // + // ############ Methods to the mode choice into form ################# // + // ################################################################### // + + /** + * Create Container to Mode choice + * + * FIXME + * don't call this._createIsoPanelFormModeChoiceTransportElement + * don't call this._createIsoPanelFormModeChoiceDirectionElement + * + * @returns {DOMElement} DOM element + */ + _createIsoPanelFormModeChoiceElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPisochronModeChoice"); + + // div.appendChild(this._createIsoPanelFormModeChoiceTransportElement()); + // div.appendChild(this._createIsoPanelFormModeChoiceDirectionElement()); + + return div; + }, + + /** + * Create Mode choice transport + * see event ! + * FIXME event not useful + * @param {Array} transports - transports in a list + * @returns {DOMElement} DOM element + */ + _createIsoPanelFormModeChoiceTransportElement : function (transports) { + // contexte d'execution + var context = this; + + var div = document.createElement("div"); + div.id = this._addUID("GPisochronTransportChoice"); + + var span = document.createElement("span"); + span.className = "GPisochronModeLabel"; + span.innerHTML = "Mode de transport"; + div.appendChild(span); + + /* jshint -W083 */ + for (var i = 0; i < transports.length; i++) { + var transport = transports[i]; + + if (transport === "Voiture") { + var inputCar = document.createElement("input"); + inputCar.id = this._addUID("GPisochronTransportCar"); + inputCar.type = "radio"; + inputCar.name = "GPisochronTransport"; + if (i === 0) { + inputCar.checked = true; + } + // gestionnaire d'evenement : + // on stocke le mode de transport, + // utilisation pour la requête sur le service de calcul d'itiniraire + if (inputCar.addEventListener) { + inputCar.addEventListener("change", function (e) { + context.onIsoModeTransportChange(e); + }); + } else if (inputCar.attachEvent) { + inputCar.attachEvent("onchange", function (e) { + context.onIsoModeTransportChange(e); + }); + } + // info : internet explorer support + inputCar.value = "Voiture"; + div.appendChild(inputCar); + + var labelCar = document.createElement("label"); + labelCar.className = "GPisochronTransportImg"; + labelCar.htmlFor = this._addUID("GPisochronTransportCar"); + labelCar.title = "Voiture"; + div.appendChild(labelCar); + } + + if (transport === "Pieton") { + var inputPedestrian = document.createElement("input"); + inputPedestrian.id = this._addUID("GPisochronTransportPedestrian"); + inputPedestrian.type = "radio"; + inputPedestrian.name = "GPisochronTransport"; + if (i === 0) { + inputPedestrian.checked = true; + } + // gestionnaire d'evenement : + // on stocke le mode de transport, + // utilisation pour la requête sur le service de calcul d'itiniraire + if (inputPedestrian.addEventListener) { + inputPedestrian.addEventListener("change", function (e) { + context.onIsoModeTransportChange(e); + }); + } else if (inputPedestrian.attachEvent) { + inputPedestrian.attachEvent("onchange", function (e) { + context.onIsoModeTransportChange(e); + }); + } + // info : internet explorer support + inputPedestrian.value = "Pieton"; + div.appendChild(inputPedestrian); + + var labelPedestrian = document.createElement("label"); + labelPedestrian.className = "GPisochronTransportImg"; + labelPedestrian.htmlFor = this._addUID("GPisochronTransportPedestrian"); + labelPedestrian.title = "Piéton"; + div.appendChild(labelPedestrian); + } + } + + return div; + }, + + /** + * Create Mode choice direction + * see event! + * + * @param {Array} directions - directions to display in list ("Departure", "Arrival"). First element will be selected by default + * @returns {DOMElement} DOM element + */ + _createIsoPanelFormModeChoiceDirectionElement : function (directions) { + // contexte d'execution + var self = this; + + var div = document.createElement("div"); + div.id = this._addUID("GPisochronDirectionChoice"); + + var span = document.createElement("span"); + span.className = "GPisochronModeLabel"; + span.innerHTML = "Sens de parcours"; + div.appendChild(span); + + var select = document.createElement("select"); + select.id = this._addUID("GPisochronDirectionSelect"); + select.className = "GPinputSelect"; + // gestionnaire d'evenement : + // on stocke la valeur du mode de calcul, + // utilisation pour la requête sur le service de calcul d'iso + select.addEventListener("change", function (e) { + self.onIsoModeDirectionChange(e); + }); + + for (var i = 0; i < directions.length; i++) { + var direction = directions[i]; + if (direction.toLowerCase() === "departure") { + var departureOption = document.createElement("option"); + if (i === 0) { + departureOption.selected = "selected"; + } + departureOption.value = "departure"; + departureOption.text = "Départ"; + select.appendChild(departureOption); + } + if (direction.toLowerCase() === "arrival") { + var arrivalOption = document.createElement("option"); + if (i === 0) { + arrivalOption.selected = "selected"; + } + arrivalOption.value = "arrival"; + arrivalOption.text = "Arrivée"; + select.appendChild(arrivalOption); + } + } + div.appendChild(select); + + return div; + }, + + // ################################################################### // + // ################# Methods to the choice exclusions ################ // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing Exclusions Options + * + * @returns {DOMElement} DOM element + */ + _createShowIsoExclusionsElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowIsoExclusions"); + input.type = "checkbox"; + return input; + }, + + /** + * Label to Exclusions Options + * + * @returns {DOMElement} DOM element + */ + _createShowIsoExclusionsPictoElement : function () { + var label = document.createElement("label"); + label.id = this._addUID("GPshowIsoExclusionsPicto"); + label.className = "GPshowMoreOptionsImage GPshowMoreOptions GPshowIsoExclusionsPicto"; + label.htmlFor = this._addUID("GPshowIsoExclusions"); + label.title = "Exclusions"; + label.style.top = "240px"; + + return label; + }, + + /** + * Create Container to Exclusions + * + * @returns {DOMElement} DOM element + */ + _createIsoPanelFormExclusionsElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPisoExclusions"); + + var span = document.createElement("span"); + span.className = "GPisoExclusionsLabel"; + span.innerHTML = "Passages autorisés"; + div.appendChild(span); + + // div.appendChild(this._createIsoPanelFormExclusionOptionsElement()); + + return div; + }, + + /** + * Create Exclusions Options + * see event ! + * FIXME event not useful + * @param {Array} exclusions - exclusions to display in list + * @returns {DOMElement} DOM element + */ + _createIsoPanelFormExclusionOptionsElement : function (exclusions) { + // contexte d'execution + var context = this; + + var div = document.createElement("div"); + div.className = "GPisoExclusionsOptions"; + + /* jshint -W083 */ + for (var value in exclusions) { + if (exclusions.hasOwnProperty(value)) { + var status = exclusions[value]; + switch (value) { + case "toll": + var inputToll = document.createElement("input"); + inputToll.id = this._addUID("GPisoExclusionsToll"); + inputToll.type = "checkbox"; + inputToll.checked = !status; + // gestionnaire d'evenement : + // on stocke l'exclusion, + // utilisation pour la requête sur le service de calcul d'itiniraire + if (inputToll.addEventListener) { + inputToll.addEventListener("change", function (e) { + context.onIsoExclusionsChange(e); + }); + } else if (inputToll.attachEvent) { + inputToll.attachEvent("onchange", function (e) { + context.onIsoExclusionsChange(e); + }); + } + // info : internet explorer support + inputToll.value = "Toll"; + div.appendChild(inputToll); + + var labelToll = document.createElement("label"); + labelToll.className = "GPisoExclusionsOption"; + labelToll.htmlFor = this._addUID("GPisoExclusionsToll"); + labelToll.innerHTML = "Péages"; + div.appendChild(labelToll); + break; + + case "tunnel": + var inputTunnel = document.createElement("input"); + inputTunnel.id = this._addUID("GPisoExclusionsTunnel"); + inputTunnel.type = "checkbox"; + inputTunnel.checked = !status; + // gestionnaire d'evenement : + // on stocke l'exclusion, + // utilisation pour la requête sur le service de calcul d'itiniraire + if (inputTunnel.addEventListener) { + inputTunnel.addEventListener("change", function (e) { + context.onIsoExclusionsChange(e); + }); + } else if (inputTunnel.attachEvent) { + inputTunnel.attachEvent("onchange", function (e) { + context.onIsoExclusionsChange(e); + }); + } + // info : internet explorer support + inputTunnel.value = "Tunnel"; + div.appendChild(inputTunnel); + + var labelTunnel = document.createElement("label"); + labelTunnel.className = "GPisoExclusionsOption"; + labelTunnel.htmlFor = this._addUID("GPisoExclusionsTunnel"); + labelTunnel.innerHTML = "Tunnels"; + div.appendChild(labelTunnel); + break; + + case "bridge": + var inputBridge = document.createElement("input"); + inputBridge.id = this._addUID("GPisoExclusionsBridge"); + inputBridge.type = "checkbox"; + inputBridge.checked = !status; + // gestionnaire d'evenement : + // on stocke l'exclusion, + // utilisation pour la requête sur le service de calcul d'itiniraire + if (inputBridge.addEventListener) { + inputBridge.addEventListener("change", function (e) { + context.onIsoExclusionsChange(e); + }); + } else if (inputBridge.attachEvent) { + inputBridge.attachEvent("onchange", function (e) { + context.onIsoExclusionsChange(e); + }); + } + // info : internet explorer support + inputBridge.value = "Bridge"; + div.appendChild(inputBridge); + + var labelBridge = document.createElement("label"); + labelBridge.className = "GPisoExclusionsOption"; + labelBridge.htmlFor = this._addUID("GPisoExclusionsBridge"); + labelBridge.innerHTML = "Ponts"; + div.appendChild(labelBridge); + break; + } + } + } + + return div; + }, + + // ################################################################### // + // ############################### Submit Form ####################### // + // ################################################################### // + + /** + * Create Submit Form Element + * + * @returns {DOMElement} DOM element + */ + _createIsoSubmitFormElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPisochronSubmit"); + input.className = "GPinputSubmit"; + input.type = "submit"; + input.value = "Calculer"; + + return input; + }, + + // ################################################################### // + // ############################### Reset picto ####################### // + // ################################################################### // + + /** + * Create Reset Picto Element + * + * @returns {DOMElement} DOM element + */ + _createIsoFormResetElement : function () { + var self = this; + + var divReset = document.createElement("div"); + divReset.id = this._addUID("GPisochronReset"); + divReset.title = "Réinitialiser les paramètres"; + divReset.addEventListener("click", function (e) { + self.onIsoResetClick(e); + }); + + return divReset; + } +}; + +export default IsoDOM; diff --git a/src/Common-review/Controls/LayerImportDOM.js b/src/Common-review/Controls/LayerImportDOM.js new file mode 100644 index 000000000..b48f46b13 --- /dev/null +++ b/src/Common-review/Controls/LayerImportDOM.js @@ -0,0 +1,1064 @@ +import SelectorID from "../Utils/SelectorID"; + +var LayerImportDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Map loading + * + * @returns {DOMElement} container + */ + _createLoadingElement : function () { + var div = document.createElement("div"); + div.id = "GPmapLoading"; + div.className = ""; + return div; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPimport"); + container.className = "GPwidget"; + return container; + }, + + // ################################################################### // + // ######################### show widget ############################# // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing + * + * @returns {DOMElement} DOM element + */ + _createShowImportElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowImport"); + input.type = "checkbox"; + return input; + }, + + /** + * Show Import + * + * @returns {DOMElement} DOM element + */ + _createShowImportPictoElement : function () { + // contexte d'execution + var self = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowImportPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowImport"); + label.title = "Ouvrir l'import de couches"; + + // Close all results and panels when minimizing the widget + if (label.addEventListener) { + label.addEventListener("click", function () { + self._onShowImportClick(); + }); + } else if (label.attachEvent) { + label.attachEvent("onclick", function () { + self._onShowImportClick(); + }); + } + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowImportOpen"); + spanOpen.className = "GPshowAdvancedToolOpen"; + label.appendChild(spanOpen); + + return label; + }, + + // ################################################################### // + // ######################### Header panel ############################ // + // ################################################################### // + + /** + * Create Container Panel + * + * @returns {DOMElement} DOM element + */ + _createImportPanelElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPimportPanel"); + div.className = "GPpanel"; + + return div; + }, + + /** + * Create Header Panel + * + * @returns {DOMElement} DOM element + */ + _createImportPanelHeaderElement : function () { + var container = document.createElement("div"); + container.className = "GPpanelHeader"; + + // panel title + var panelTitle = this._createImportPanelTitleElement(); + container.appendChild(panelTitle); + // close picto + var closeDiv = this._createImportPanelCloseElement(); + container.appendChild(closeDiv); + + return container; + }, + + /** + * Create Header Title Panel + * + * @returns {DOMElement} DOM element + */ + _createImportPanelTitleElement : function () { + var div = document.createElement("div"); + div.className = "GPpanelTitle"; + div.innerHTML = "Import de données"; + return div; + }, + + /** + * Create Header close div + * + * @returns {DOMElement} DOM element + */ + _createImportPanelCloseElement : function () { + // contexte + var self = this; + + var divClose = document.createElement("div"); + divClose.id = this._addUID("GPimportPanelClose"); + divClose.className = "GPpanelClose"; + divClose.title = "Fermer le panneau"; + + // Link panel close / visibility checkbox + if (divClose.addEventListener) { + divClose.addEventListener("click", function () { + document.getElementById(self._addUID("GPshowImportPicto")).click(); + }, false); + } else if (divClose.attachEvent) { + divClose.attachEvent("onclick", function () { + document.getElementById(self._addUID("GPshowImportPicto")).click(); + }); + } + + return divClose; + }, + + // ################################################################### // + // ########################### Form panel ############################ // + // ################################################################### // + + /** + * Create Form + * see event ! + * + * @returns {DOMElement} DOM element + */ + _createImportPanelFormElement : function () { + // contexte d'execution + var self = this; + + var form = document.createElement("form"); + form.id = this._addUID("GPimportForm"); + form.className = "map-tool-box"; + + // TODO ? + if (form.addEventListener) { + form.addEventListener("submit", function (e) { + e.preventDefault(); + self._onImportSubmit(); + }); + } else if (form.attachEvent) { + form.attachEvent("onsubmit", function (e) { + e.preventDefault(); + self._onImportSubmit(); + }); + } + + return form; + }, + + /** + * Create Container for import type choice + * + * @param {Array} importTypes - import types to be displayed (and used) + * @returns {DOMElement} DOM element + */ + _createImportTypeLineElement : function (importTypes) { + // contexte d'execution + var context = this; + + var div = document.createElement("div"); + div.id = this._addUID("GPimportTypeLine"); + div.className = "GPimportInputLine"; + + var label = document.createElement("label"); + label.htmlFor = this._addUID("GPimportType"); + label.className = "GPimportLabel"; + label.innerHTML = "Type de donnée"; + label.title = "Type de donnée"; + div.appendChild(label); + + var select = document.createElement("select"); + select.className = "GPimportSelect"; + // gestionnaire d'evenement : on stocke la valeur du type d'import + if (select.addEventListener) { + select.addEventListener("change", function (e) { + if (this.value === "KML" || this.value === "GPX" || this.value === "GeoJSON" || this.value === "MAPBOX") { + // static import + document.getElementById(context._addUID("GPimportStaticParams")).className = "GPimportVisibleParams"; + document.getElementById(context._addUID("GPimportServiceParams")).className = "GPimportHiddenParams"; + } else if (this.value === "WMS" || this.value === "WMTS" || this.value === "WFS") { + // service import + document.getElementById(context._addUID("GPimportServiceParams")).className = "GPimportVisibleParams"; + document.getElementById(context._addUID("GPimportStaticParams")).className = "GPimportHiddenParams"; + } + context._onImportTypeChange(e); + }); + } else if (select.attachEvent) { + select.attachEvent("onchange", function () { + if (this.value === "KML" || this.value === "GPX" || this.value === "GeoJSON" || this.value === "MAPBOX") { + // static import + document.getElementById(context._addUID("GPimportStaticParams")).className = "GPimportVisibleParams"; + document.getElementById(context._addUID("GPimportServiceParams")).className = "GPimportHiddenParams"; + } else if (this.value === "WMS" || this.value === "WMTS" || this.value === "WFS") { + // service import + document.getElementById(context._addUID("GPimportServiceParams")).className = "GPimportVisibleParams"; + document.getElementById(context._addUID("GPimportStaticParams")).className = "GPimportHiddenParams"; + } + context._onImportTypeChange(); + }); + } + select.id = this._addUID("GPimportType"); + + // on prend soit les valeurs passées par l'utilisateur, soit des valeurs par défaut + if (!importTypes || !Array.isArray(importTypes)) { + importTypes = [ + "KML", + "GPX", + "GeoJSON", + "MAPBOX", + "WMS", + "WMTS", + "WFS" + ]; + } + var option; + for (var i = 0; i < importTypes.length; i++) { + option = document.createElement("option"); + option.value = importTypes[i]; + option.text = (importTypes[i] === "MAPBOX") ? "Vecteur tuilé" : importTypes[i]; + select.appendChild(option); + } + + div.appendChild(select); + + return div; + }, + + /** + * Create Waiting Panel + * + * @returns {DOMElement} DOM element + */ + _createImportWaitingElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPimportWaitingContainer"); + div.className = "GPimportWaitingContainerHidden"; + + var p = document.createElement("p"); + p.className = "GPimportWaiting"; + p.innerHTML = "Recherche en cours..."; + + div.appendChild(p); + + return div; + }, + + // ################################################################### // + // ##### Params for static import (KML / GPX / GeoJSON) ############## // + // ################################################################### // + + /** + * Create container for KML/GPX/GeoJSON parameters + * @param {String} currentType - GeoJSON, GPX or KML value + * @returns {DOMElement} DOM element + */ + _createImportStaticParamsContainer : function (currentType) { + var div = document.createElement("div"); + div.id = this._addUID("GPimportStaticParams"); + if (currentType === "KML" || currentType === "GPX" || currentType === "GeoJSON" || currentType === "MAPBOX") { + div.className = "GPimportVisibleParams"; + } else { + div.className = "GPimportHiddenParams"; + } + + return div; + }, + + /** + * Create name label for KML/GPX/GeoJSON parameters + * + * @returns {DOMElement} DOM element + */ + _createStaticNameLabel : function () { + var div = document.createElement("div"); + div.className = "GPimportInputLine"; + + var label = document.createElement("label"); + label.className = "GPimportLabel"; + label.htmlFor = this._addUID("GPimportName"); + label.innerHTML = "Nom"; + label.title = "Nom"; + div.appendChild(label); + + var input = document.createElement("input"); + input.type = "text"; + input.id = this._addUID("GPimportName"); + input.className = "GPimportInput"; + div.appendChild(input); + + return div; + }, + + /** + * Create import choice for KML/GPX/GeoJSON parameters (local or url) + * + * @returns {DOMElement} DOM element + */ + _createStaticModeChoiceDiv : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPimportChoice"); + return div; + }, + + /** + * Create local import choice for KML/GPX/GeoJSON parameters + * + * @returns {DOMElement} DOM element + */ + _createStaticLocalChoiceDiv : function () { + var context = this; + + var div = document.createElement("div"); + div.className = "GPimportChoiceAlt"; + + var input = document.createElement("input"); + input.type = "radio"; + if (input.addEventListener) { + input.addEventListener("change", function (e) { + document.getElementById(context._addUID("GPimportValueLocal")).className = "GPimportInputLine"; + document.getElementById(context._addUID("GPimportValueUrl")).className = "GPimportValueHidden"; + context._onStaticImportTypeChange(e); + }); + } else if (input.appendChild) { + input.appendChild("onchange", function () { + document.getElementById(context._addUID("GPimportValueLocal")).className = "GPimportInputLine"; + document.getElementById(context._addUID("GPimportValueUrl")).className = "GPimportValueHidden"; + context._onStaticImportTypeChange(); + }); + } + input.name = "GPimportChoiceMode"; + input.value = "local"; + input.checked = true; + input.id = this._addUID("GPimportChoiceAltLocal"); + div.appendChild(input); + + var label = document.createElement("label"); + label.className = "GPimportChoiceAltTxt"; + label.htmlFor = this._addUID("GPimportChoiceAltLocal"); + label.innerHTML = "par fichier local"; + label.title = "par fichier local"; + div.appendChild(label); + + return div; + }, + + /** + * Create url import choice for KML/GPX/GeoJSON parameters + * + * @returns {DOMElement} DOM element + */ + _createStaticUrlChoiceDiv : function () { + var context = this; + + var div = document.createElement("div"); + div.className = "GPimportChoiceAlt"; + + var input = document.createElement("input"); + input.type = "radio"; + if (input.addEventListener) { + input.addEventListener("change", function (e) { + document.getElementById(context._addUID("GPimportValueUrl")).className = "GPimportInputLine"; + document.getElementById(context._addUID("GPimportValueLocal")).className = "GPimportValueHidden"; + context._onStaticImportTypeChange(e); + }); + } else if (input.appendChild) { + input.appendChild("onchange", function () { + document.getElementById(context._addUID("GPimportValueUrl")).className = "GPimportInputLine"; + document.getElementById(context._addUID("GPimportValueLocal")).className = "GPimportValueHidden"; + context._onStaticImportTypeChange(); + }); + } + input.id = this._addUID("GPimportChoiceAltUrl"); + input.name = "GPimportChoiceMode"; + input.value = "url"; + input.checked = false; + div.appendChild(input); + + var label = document.createElement("label"); + label.className = "GPimportChoiceAltTxt"; + label.htmlFor = this._addUID("GPimportChoiceAltUrl"); + label.innerHTML = "par URL"; + label.title = "par URL"; + div.appendChild(label); + + return div; + }, + + /** + * Create input div for KML/GPX/GeoJSON parameters local import + * + * @returns {DOMElement} DOM element + */ + _createStaticLocalInputDiv : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPimportValueLocal"); + div.className = "GPimportInputLine"; + return div; + }, + + /** + * Create input label for KML/GPX/GeoJSON parameters local import + * + * @returns {DOMElement} DOM element + */ + _createStaticLocalInputLabel : function () { + var label = document.createElement("label"); + label.className = "GPimportLabel"; + label.htmlFor = this._addUID("GPimportFile"); + label.innerHTML = "Fichier local"; + label.title = "Fichier local"; + return label; + }, + + /** + * Create file input for KML/GPX/GeoJSON parameters local import + * + * @returns {DOMElement} DOM element + */ + _createStaticLocalInput : function () { + var input = document.createElement("input"); + input.type = "file"; + input.id = this._addUID("GPimportFile"); + input.className = "GPimportInputFile"; + return input; + }, + + /** + * Create input div for KML/GPX/GeoJSON parameters url import + * + * @returns {DOMElement} DOM element + */ + _createStaticUrlInputDiv : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPimportValueUrl"); + div.className = "GPimportValueHidden"; + return div; + }, + + /** + * Create input label for KML/GPX/GeoJSON parameters url import + * + * @returns {DOMElement} DOM element + */ + _createStaticUrlInputLabel : function () { + var label = document.createElement("label"); + label.className = "GPimportLabel"; + label.htmlFor = this._addUID("GPimportUrl"); + label.innerHTML = "URL"; + label.title = "URL"; + return label; + }, + + /** + * Create url input for KML/GPX/GeoJSON parameters url import + * + * @returns {DOMElement} DOM element + */ + _createStaticUrlInput : function () { + var input = document.createElement("input"); + input.type = "text"; + input.id = this._addUID("GPimportUrl"); + input.className = "GPimportInput"; + return input; + }, + + // ################################################################### // + // ######## Params for service params import (WMS//WMTS/WFS) ######### // + // ################################################################### // + + /** + * Create container for WMS/WMTS/WFS parameters + * @param {String} currentType - WMS, WMTS or WFS value + * @returns {DOMElement} DOM element + */ + _createServiceParamsContainer : function (currentType) { + var div = document.createElement("div"); + div.id = this._addUID("GPimportServiceParams"); + if (currentType === "WMS" || currentType === "WMTS" || currentType === "WFS") { + div.className = "GPimportVisibleParams"; + } else { + div.className = "GPimportHiddenParams"; + } + + return div; + }, + + /** + * Create div for WMS/WMTS/WFS url + * + * @returns {DOMElement} DOM element + */ + _createServiceUrlDiv : function () { + var div = document.createElement("div"); + div.className = "GPimportInputLine"; + return div; + }, + + /** + * Create input label for WMS/WMTS/WFS url + * + * @returns {DOMElement} DOM element + */ + _createServiceUrlInputLabel : function () { + var label = document.createElement("label"); + label.className = "GPimportLabel"; + label.htmlFor = this._addUID("GPimportServiceUrl"); + label.innerHTML = "URL du service"; + label.title = "URL du service"; + return label; + }, + + /** + * Create input for WMS/WMTS/WFS parameters url + * + * @returns {DOMElement} DOM element + */ + _createServiceUrlInput : function () { + var input = document.createElement("input"); + input.type = "text"; + input.id = this._addUID("GPimportServiceUrl"); + input.className = "GPimportInput"; + return input; + }, + + // ################################################################### // + // ########################### Submit Form ########################### // + // ################################################################### // + + /** + * Create Submit Form Element + * + * @returns {DOMElement} DOM element + */ + _createImportSubmitFormElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPimportSubmit"); + input.className = "GPinputSubmit tool-form-submit"; + input.type = "submit"; + input.value = "Importer"; + + return input; + }, + + // ################################################################### // + // ########################### GetCap Panel ########################## // + // ################################################################### // + + /** + * Create GetCap Panel Element + * + * @returns {DOMElement} DOM element + */ + _createImportGetCapPanelElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPimportGetCapPanel"); + div.className = "GPpanel"; + return div; + }, + + /** + * Create GetCap Panel Header Element + * + * @returns {DOMElement} DOM element + */ + _createImportGetCapPanelHeaderElement : function () { + // contexte + var context = this; + + var container = document.createElement("div"); + container.className = "GPpanelHeader"; + + // panel title + var panelTitle = document.createElement("div"); + panelTitle.className = "GPpanelTitle"; + panelTitle.innerHTML = "Couches accessibles"; + panelTitle.title = "Couches accessibles"; + container.appendChild(panelTitle); + + // close picto + var closeDiv = document.createElement("div"); + if (closeDiv.addEventListener) { + closeDiv.addEventListener("click", function () { + document.getElementById(context._addUID("GPimportGetCapPanel")).style.display = "none"; + document.getElementById(context._addUID("GPimportPanel")).style.display = ""; + context._onGetCapPanelClose(); + }); + } else if (closeDiv.attachEvent) { + closeDiv.attachEvent("click", function () { + document.getElementById(context._addUID("GPimportGetCapPanel")).style.display = "none"; + document.getElementById(context._addUID("GPimportPanel")).style.display = ""; + context._onGetCapPanelClose(); + }); + } + closeDiv.className = "GPpanelClose"; + closeDiv.title = "Fermer le panneau"; + closeDiv.id = this._addUID("GPimportGetCapPanelClose"); + container.appendChild(closeDiv); + + return container; + }, + + /** + * Create GetCap Results List Element + * + * @returns {DOMElement} DOM element + */ + _createImportGetCapResultsContainer : function () { + var container = document.createElement("div"); + container.className = "GPimportGetCapRoot"; + container.id = this._addUID("GPimportGetCapResults"); + + return container; + }, + + _addImportGetCapResultListRubrique : function (title, container) { + var ul = document.createElement("ul"); + ul.className = "GPimportGetCapListRubrique"; + ul.title = title; + + container.appendChild(ul); + return container; + }, + + _addImportGetCapResultRubrique : function (title, container) { + var li = document.createElement("li"); + li.className = "GPimportGetCapRubrique"; + + // input + var input = document.createElement("input"); + input.id = "GPimportGetCapRubrique-" + SelectorID.generate(); + input.className = "GPimportGetCapRubrique"; + input.type = "checkbox"; + li.appendChild(input); + + // label for + var label = document.createElement("label"); + label.className = "GPimportGetCapRubriqueTitle"; + label.htmlFor = input.id; + label.innerHTML = title; + label.title = title; + li.appendChild(label); + + container.appendChild(li); + return container; + }, + + _addImportGetCapResultListLayer : function (container) { + var ul = document.createElement("ul"); + ul.className = "GPimportGetCapListLayer"; + + container.appendChild(ul); + return container; + }, + + _addImportGetCapResultLayer : function (description, id, container) { + var li = document.createElement("li"); + li.className = "GPimportGetCapProposal"; + li.innerHTML = description.content; + li.title = description.title; + li.id = "GPimportGetCapProposal_" + id; + + var context = this; + if (li.addEventListener) { + li.addEventListener("click", function (e) { + context._onGetCapResponseLayerClick(e); + }); + } else if (li.attachEvent) { + li.attachEvent("onclick", function () { + context._onGetCapResponseLayerClick(); + }); + } + + container.appendChild(li); + return container; + }, + + // ################################################################### // + // ########################### MapBox Panel ########################## // + // ################################################################### // + + /** + * Create MapBox Panel Element + * + * @returns {DOMElement} DOM element + */ + _createImportMapBoxPanelElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPimportMapBoxPanel"); + div.className = "GPpanel"; + return div; + }, + + /** + * Create MapBox Panel Header Element + * + * @returns {DOMElement} DOM element + */ + _createImportMapBoxPanelHeaderElement : function () { + // contexte + var context = this; + + var container = document.createElement("div"); + container.className = "GPpanelHeader"; + + // return picto + var returnDiv = document.createElement("div"); + returnDiv.id = this._addUID("GPimportMapBoxPanelReturnPicto"); + returnDiv.title = "Masquer le panneau"; + returnDiv.className = ""; + if (returnDiv.addEventListener) { + returnDiv.addEventListener("click", function (e) { + // document.getElementById(context._addUID("GPimportMapBoxPanel")).style.display = "none"; + // document.getElementById(context._addUID("GPimportPanel")).style.display = "none"; + context._onMapBoxReturnPictoClick(e); + }); + } else if (returnDiv.attachEvent) { + returnDiv.attachEvent("onclick", function (e) { + // document.getElementById(context._addUID("GPimportMapBoxPanel")).style.display = "none"; + // document.getElementById(context._addUID("GPimportPanel")).style.display = "none"; + context._onMapBoxReturnPictoClick(e); + }); + } + container.appendChild(returnDiv); + + // panel title + var panelTitle = document.createElement("div"); + panelTitle.className = "GPpanelTitle"; + panelTitle.innerHTML = "Edition des styles"; + panelTitle.title = "Edition des styles"; + container.appendChild(panelTitle); + + // close picto + var closeDiv = document.createElement("div"); + if (closeDiv.addEventListener) { + closeDiv.addEventListener("click", function () { + document.getElementById(context._addUID("GPimportMapBoxPanel")).style.display = "none"; + document.getElementById(context._addUID("GPimportPanel")).style.display = ""; + context._onMapBoxPanelClose(); + }); + } else if (closeDiv.attachEvent) { + closeDiv.attachEvent("click", function () { + document.getElementById(context._addUID("GPimportMapBoxPanel")).style.display = "none"; + document.getElementById(context._addUID("GPimportPanel")).style.display = ""; + context._onMapBoxPanelClose(); + }); + } + closeDiv.className = "GPpanelClose"; + closeDiv.title = "Fermer le panneau"; + closeDiv.id = this._addUID("GPimportMapBoxPanelClose"); + container.appendChild(closeDiv); + + return container; + }, + + /** + * Create MapBox Results List Element + * + * @returns {DOMElement} DOM element + */ + _createImportMapBoxResultsContainer : function () { + var container = document.createElement("div"); + container.className = "GPimportMapBoxpRoot"; + container.id = this._addUID("GPimportMapBoxResults"); + return container; + } + + // _addImportMapBoxResultListSource : function (id, source, container) { + // var ul = document.createElement("ul"); + // ul.className = "GPimportMapBoxListSource"; + // ul.title = id; + // + // var label = document.createElement("label"); + // label.className = "GPimportMapBoxListSourceTitle"; + // label.innerHTML = "Listes des couches pour la source '" + id + "' :"; + // label.title = source.attribution || id; + // ul.appendChild(label); + // + // container.appendChild(ul); + // return container; + // }, + // + // _addImportMapBoxResultSource : function (layer, container) { + // var li = document.createElement("li"); + // li.className = "GPimportMapBoxSource"; + // + // // input + // var input = document.createElement("input"); + // input.id = "GPimportMapBoxSource-" + SelectorID.generate(); + // input.className = "GPimportMapBoxSource"; + // input.type = "checkbox"; + // li.appendChild(input); + // + // // label for + // var name = layer["source-layer"] || layer.id || layer.source; + // var label = document.createElement("label"); + // label.className = "GPimportMapBoxSourceTitle"; + // label.htmlFor = input.id; + // label.innerHTML = name; + // label.title = JSON.stringify(layer.metadata) || name; + // li.appendChild(label); + // + // container.appendChild(li); + // return container; + // }, + // + // _addImportMapBoxStyleSource : function (layer, container) { + // // contexte + // var self = this; + // + // var _style = false; + // var _obj = {}; + // var _layer = JSON.parse(JSON.stringify(layer)); // on utilise une copie ! + // if (_layer.paint && Object.keys(_layer.paint).length) { + // _style = true; + // _obj.paint = _layer.paint; + // } + // + // // pas de style dans paint, on teste dans layout ! + // if (_layer.layout && Object.keys(_layer.layout).length) { + // _style = true; + // _obj.layout = _layer.layout; + // // on supprime visibility à l'affichage uniquement + // // cf. _addImportMapBoxVisibilitySource ! + // if (_layer.layout.visibility) { + // delete _obj.visibility; + // } + // } + // + // function syntaxHighlight (json) { + // json = json.replace(/&/g, "&").replace(//g, ">"); + // return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g, function (match) { + // var cls = "gp-json-number"; + // if (/^"/.test(match)) { + // if (/:$/.test(match)) { + // cls = "gp-json-key"; + // } else { + // cls = "gp-json-string"; + // } + // } else if (/true|false/.test(match)) { + // cls = "gp-json-boolean"; + // } else if (/null/.test(match)) { + // cls = "gp-json-null"; + // } + // return "" + match + ""; + // }); + // } + // + // var div = document.createElement("div"); + // div.className = "GPimportMapBoxSourceStyle"; + // + // if (_style) { + // var strJson = JSON.stringify(_obj, null, 4); + // + // var label = document.createElement("label"); + // label.innerHTML = "JSON Styles :"; + // div.appendChild(label); + // var pre = document.createElement("pre"); + // pre.className = "GPimportMapBoxJsonEdit"; + // pre.innerHTML = syntaxHighlight(strJson); + // if (pre.addEventListener) { + // pre.addEventListener("click", function (e) { + // self._onSwitchStyleEditSourceMapBox(e); + // }); + // } else if (pre.appendChild) { + // pre.appendChild("onclick", function (e) { + // self._onSwitchStyleEditSourceMapBox(e); + // }); + // } + // div.appendChild(pre); + // } + // + // container.appendChild(div); + // return container; + // }, + // + // _addImportMapBoxFilterSource : function (layer, container) { + // // contexte + // var self = this; + // + // var _filter = false; + // // FIXME tag filter est obselete ! + // // on doit utiliser les expressions dans "paint" ou "layout" ! + // if (layer.filter && layer.filter.length) { + // _filter = true; + // } + // + // var div = document.createElement("div"); + // div.className = "GPimportMapBoxSourceFilter"; + // + // if (_filter) { + // var label = document.createElement("label"); + // label.innerHTML = "JSON Filtres :"; + // div.appendChild(label); + // var pre = document.createElement("pre"); + // pre.className = "GPimportMapBoxJsonEdit"; + // pre.innerHTML = JSON.stringify(layer.filter, null, 4); + // if (pre.addEventListener) { + // pre.addEventListener("click", function (e) { + // self._onSwitchFilterEditSourceMapBox(e); + // }); + // } else if (pre.appendChild) { + // pre.appendChild("onclick", function (e) { + // self._onSwitchFilterEditSourceMapBox(e); + // }); + // } + // div.appendChild(pre); + // } + // + // container.appendChild(div); + // return container; + // }, + // + // _addImportMapBoxScaleSource : function (layer, container) { + // // contexte + // var self = this; + // + // var _scaleMin = layer.minzoom || 0; + // var _scaleMax = layer.maxzoom || 21; + // + // var div = document.createElement("div"); + // div.className = "GPimportMapBoxSourceScale"; + // + // var labelMin = document.createElement("label"); + // labelMin.className = "GPimportMapBoxSourceScaleLabel"; + // labelMin.innerHTML = "minZoom :"; + // div.appendChild(labelMin); + // + // var inputMin = document.createElement("input"); + // inputMin.className = "GPimportMapBoxSourceScaleInput"; + // inputMin.type = "range"; + // inputMin.value = _scaleMin; + // inputMin.title = _scaleMin; + // inputMin.disabled = false; + // inputMin.min = 0; + // inputMin.max = 21; + // if (inputMin.addEventListener) { + // inputMin.addEventListener("change", function (e) { + // self._onChangeScaleMinSourceMapBox(e, layer); + // }); + // } else if (inputMin.appendChild) { + // inputMin.appendChild("onchange", function (e) { + // self._onChangeScaleMinSourceMapBox(e, layer); + // }); + // } + // div.appendChild(inputMin); + // + // div.appendChild(document.createElement("br")); + // + // var labelMax = document.createElement("label"); + // labelMax.className = "GPimportMapBoxSourceScaleLabel"; + // labelMax.innerHTML = "maxZoom :"; + // div.appendChild(labelMax); + // + // var inputMax = document.createElement("input"); + // inputMax.className = "GPimportMapBoxSourceScaleInput"; + // inputMax.type = "range"; + // inputMax.value = _scaleMax; + // inputMax.title = _scaleMax; + // inputMax.disabled = false; + // inputMax.min = 0; + // inputMax.max = 21; + // if (inputMax.addEventListener) { + // inputMax.addEventListener("change", function (e) { + // self._onChangeScaleMaxSourceMapBox(e, layer); + // }); + // } else if (inputMax.appendChild) { + // inputMax.appendChild("onchange", function (e) { + // self._onChangeScaleMaxSourceMapBox(e, layer); + // }); + // } + // div.appendChild(inputMax); + // + // container.appendChild(div); + // return container; + // }, + // + // _addImportMapBoxVisibilitySource : function (layer, container) { + // // contexte + // var self = this; + // + // var _visibility = true; + // if (layer.layout && layer.layout.visibility && layer.layout.visibility === "none") { + // _visibility = false; + // } + // + // var div = document.createElement("div"); + // div.className = "GPimportMapBoxSourceVisibility"; + // + // var label = document.createElement("label"); + // label.className = "GPimportMapBoxSourceVisibilityLabel"; + // label.innerHTML = "Visibilité :"; + // div.appendChild(label); + // + // var input = document.createElement("input"); + // input.className = "GPimportMapBoxSourceVisibilityInput"; + // input.type = "checkbox"; + // input.checked = _visibility; + // input.disabled = false; + // if (input.addEventListener) { + // input.addEventListener("change", function (e) { + // self._onChangeVisibilitySourceMapBox(e, layer); + // }); + // } else if (input.appendChild) { + // input.appendChild("onchange", function (e) { + // self._onChangeVisibilitySourceMapBox(e, layer); + // }); + // } + // div.appendChild(input); + // + // container.appendChild(div); + // return container; + // } +}; + +export default LayerImportDOM; diff --git a/src/Common-review/Controls/LayerSwitcherDOM.js b/src/Common-review/Controls/LayerSwitcherDOM.js new file mode 100644 index 000000000..7ccd92fe2 --- /dev/null +++ b/src/Common-review/Controls/LayerSwitcherDOM.js @@ -0,0 +1,676 @@ +import Sortable from "sortablejs"; + +var LayerSwitcherDOM = { + + /** + * Creation du drag and drop + * + * @param {Object} elementDraggable - Element HTML (DOM) Container + * @param {Object} context - this + */ + _createDraggableElement : function (elementDraggable, context) { + Sortable.create(elementDraggable, { + handle : ".GPlayerName", + draggable : ".draggable-layer", + ghostClass : "GPghostLayer", + animation : 200, + // Call event function on drag and drop + onEnd : function (e) { + // FIXME pas terrrible, mais il faut bien passer ce contexte... + context._onDragAndDropLayerClick(e); + } + }); + }, + + // ################################################################### // + // ######################### Main container ########################## // + // ################################################################### // + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Creation du container principal (DOM) + * + * @returns {DOMElement} container - layer switcher DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPlayerSwitcher"); + container.className = "GPwidget"; + return container; + }, + + /** + * Creation du container principal d"affichage des layers (DOM) + * + * @returns {DOMElement} input - element for minimizing/maximizing the layer switcher + */ + _createMainLayersShowElement : function () { + // + var input = document.createElement("input"); + input.id = this._addUID("GPshowLayersList"); + input.type = "checkbox"; + return input; + }, + + /** + * Creation du container principal des layers (DOM) + * + * @returns {DOMElement} container - layers list container + */ + _createMainLayersElement : function () { + // ajout de la liste des layers dans le container principal + //
+ // (...) + //
+ var div = document.createElement("div"); + div.id = this._addUID("GPlayersList"); + div.className = "GPpanel"; + return div; + }, + + /** + * Creation du container du picto du controle (DOM) + * + * @returns {DOMElement} label + */ + _createMainPictoElement : function () { + var self = this; + + // exemple : + // + // + + var label = document.createElement("label"); + label.id = this._addUID("GPshowLayersListPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowLayersList"); + label.title = "Afficher/masquer le gestionnaire de couches"; + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowLayersListOpen"); + spanOpen.className = "GPshowAdvancedToolOpen"; + spanOpen.addEventListener("click", function () { + if (document.getElementById(self._addUID("GPshowLayersList")).checked) { + var layers = document.getElementsByClassName("GPlayerInfoOpened"); + for (var i = 0; i < layers.length; i++) { + layers[i].className = "GPlayerInfo"; + } + document.getElementById(self._addUID("GPlayerInfoPanel")).className = "GPlayerInfoPanelClosed"; + } + }); + + label.appendChild(spanOpen); + + var spanClose = document.createElement("span"); + spanClose.addEventListener("click", function () { + if (document.getElementById(self._addUID("GPshowLayersList")).checked) { + var layers = document.getElementsByClassName("GPlayerInfoOpened"); + for (var i = 0; i < layers.length; i++) { + layers[i].className = "GPlayerInfo"; + } + document.getElementById(self._addUID("GPlayerInfoPanel")).className = "GPlayerInfoPanelClosed"; + } + }); + spanClose.id = self._addUID("GPshowLayersListClose"); + + label.appendChild(spanClose); + + return label; + }, + + /** + * Creation du container du panneau d"information (DOM) + * + * @returns {DOMElement} container + */ + _createMainInfoElement : function () { + // gestion du panneau d"information dans le container principal + //
...
+ var div = document.createElement("div"); + div.id = this._addUID("GPlayerInfoPanel"); + div.className = "GPpanel GPlayerInfoPanelClosed"; + return div; + }, + + // ################################################################### // + // ######################### Layer container ######################### // + // ################################################################### // + + /** + * Creation du container du layer (DOM) + * + * @param {Object} obj - options de la couche à ajouter dans le layer switcher + * @param {Object} obj.layer - couche (ol ou leaflet) + * @param {String} obj.id - identifiant de la couche (pour ol ou leaflet) + * @param {String} obj.title - nom de la couche à afficher dans le controle + * @param {String} obj.description - description de la couche à afficher + * @param {Boolean} obj.visibility - visibilité de la couche dans la carte (true or false) + * @param {Float} obj.opacity - opacité de la couche + * + * @returns {DOMElement} container + */ + _createContainerLayerElement : function (obj) { + // exemple : + //
+ // + // + // + //
+ + // + // + var container = document.createElement("div"); + container.id = this._addUID("GPlayerSwitcher_ID_" + obj.id); + container.className = "GPlayerSwitcher_layer draggable-layer"; + + // ajout des outils basiques (visibility / layer name) + container.appendChild(this._createBasicToolElement(obj)); + + // liste des outils avancés (layer info / opacity slider / opacity value / removal) + var array = this._createAdvancedToolShowElement(obj); + for (var i = 0; i < array.length; i++) { + container.appendChild(array[i]); + } + + // ajout des outils avancés + container.appendChild(this._createAdvancedToolElement(obj)); + + return container; + }, + + // ################################################################### // + // ############################ Layer tool ########################### // + // ################################################################### // + + /** + * Creation du container des outils basiques du layer (DOM) + * + * @param {Object} obj - options de la couche à ajouter dans le layer switcher + * + * @returns {DOMElement} container + */ + _createBasicToolElement : function (obj) { + // exemple : + //
+ // + // + //
+ + var div = document.createElement("div"); + div.id = this._addUID("GPbasicTools_ID_" + obj.id); + div.className = "GPlayerBasicTools"; + + div.appendChild(this._createBasicToolNameElement(obj)); + + var array = this._createBasicToolVisibilityElement(obj); + for (var i = 0; i < array.length; i++) { + div.appendChild(array[i]); + } + + return div; + }, + + /** + * Creation du nom du layer (DOM) + * + * @param {Object} obj - options de la couche à ajouter dans le layer switcher + * + * @returns {DOMElement} container + */ + _createBasicToolNameElement : function (obj) { + // exemple : + // Quartiers prioritaires de la ville + var span = document.createElement("span"); + span.id = this._addUID("GPname_ID_" + obj.id); + span.className = "GPlayerName"; + span.title = obj.description || obj.title; + span.innerHTML = obj.title; + + return span; + }, + + /** + * Creation de l'icone de visibilité du layer (DOM) + * + * @param {Object} obj - options de la couche à ajouter dans le layer switcher + + * @returns {DOMElement[]} array containing input and label elements + */ + _createBasicToolVisibilityElement : function (obj) { + // exemple : + // + // + + var list = []; + + var checked = (typeof obj.visibility !== "undefined") ? obj.visibility : true; + var id = this._addUID("GPvisibility_ID_" + obj.id); + + var input = document.createElement("input"); + input.id = id; + input.type = "checkbox"; + input.checked = checked; + + var label = document.createElement("label"); + label.htmlFor = id; + label.id = this._addUID("GPvisibilityPicto_ID_" + obj.id); + label.className = "GPlayerVisibility"; + label.title = "Afficher/masquer la couche"; + + // add event for visibility change + var context = this; + if (input.addEventListener) { + input.addEventListener( + "click", + function (e) { + context._onVisibilityLayerClick(e); + } + ); + } else if (input.attachEvent) { + // internet explorer + input.attachEvent( + "onclick", + function (e) { + context._onVisibilityLayerClick(e); + } + ); + } + + list.push(input); + list.push(label); + + return list; + }, + + /** + * Creation de l'affichage du menu des outils avancés du layer (DOM) + * + * @param {Object} obj - options de la couche à ajouter dans le layer switcher + * + * @returns {DOMElement[]} array containing input and label elements + */ + _createAdvancedToolShowElement : function (obj) { + // + // + + var list = []; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowAdvancedToolsPicto_ID_" + obj.id); + label.htmlFor = this._addUID("GPshowAdvancedTools_ID_" + obj.id); + label.title = "Plus d'outils"; + label.className = "GPshowMoreOptions GPshowLayerAdvancedTools"; + + var input = document.createElement("input"); + input.type = "checkbox"; + input.id = this._addUID("GPshowAdvancedTools_ID_" + obj.id); + + list.push(input); + list.push(label); + + return list; + }, + + /** + * Creation du container des outils avancés du layer (DOM) + * + * @param {Object} obj - options de la couche à ajouter dans le layer switcher + * + * @returns {DOMElement} container + */ + _createAdvancedToolElement : function (obj) { + // exemple : + //
+ // + // + // + //
+ + var container = document.createElement("div"); + container.id = this._addUID("GPadvancedTools_ID_" + obj.id); + container.className = "GPlayerAdvancedTools"; + + container.appendChild(this._createAdvancedToolDeleteElement(obj)); + + // si on n'a de l'informations à afficher, on met en place ce composant + if (obj.title && obj.description) { + container.appendChild(this._createAdvancedToolInformationElement(obj)); + } + if (obj.type !== "feature") { + var array = this._createAdvancedToolOpacityElement(obj); + for (var i = 0; i < array.length; i++) { + container.appendChild(array[i]); + } + } + + return container; + }, + + /** + * Creation de l'icone de suppression du layer (DOM) + * + * @param {Object} obj - options de la couche à ajouter dans le layer switcher + * + * @returns {DOMElement} container + */ + _createAdvancedToolDeleteElement : function (obj) { + // exemple : + //
+ + var div = document.createElement("div"); + div.id = this._addUID("GPremove_ID_" + obj.id); + div.className = "GPlayerRemove"; + div.title = "Supprimer la couche"; + div.layerId = obj.id; + + var context = this; + if (div.addEventListener) { + div.addEventListener( + "click", + function (e) { + context._onDropLayerClick(e); + } + ); + } else if (div.attachEvent) { + // internet explorer + div.attachEvent( + "onclick", + function (e) { + context._onDropLayerClick(e); + } + ); + } + + return div; + }, + + /** + * Creation de l'icone d'information du layer (DOM) + * + * @param {Object} obj - options de la couche à ajouter dans le layer switcher + * + * @returns {DOMElement} container + */ + _createAdvancedToolInformationElement : function (obj) { + // exemple : + //
+ + var div = document.createElement("div"); + div.id = this._addUID("GPinfo_ID_" + obj.id); + div.className = "GPlayerInfo"; + div.title = "Informations/légende"; + div.layerId = obj.id; + // add event on click + var context = this; + if (div.addEventListener) { + div.addEventListener( + "click", + function (e) { + context._onOpenLayerInfoClick(e); + } + ); + } else if (div.attachEvent) { + // internet explorer + div.attachEvent( + "onclick", + function (e) { + context._onOpenLayerInfoClick(e); + } + ); + } + + return div; + }, + + /** + * Creation de l'icone de gestion de l'opacité du layer (DOM) + * + * @param {Object} obj - options de la couche à ajouter dans le layer switcher + * + * @returns {DOMElement[]} array of two containers + */ + _createAdvancedToolOpacityElement : function (obj) { + // exemple : + //
+ // + //
+ //
+ // 100 + // % + //
+ + var list = []; + + // curseur pour changer l'opacité + var divO = document.createElement("div"); + divO.id = this._addUID("GPopacity_ID_" + obj.id); + divO.className = "GPlayerOpacity"; + divO.title = "Opacité"; + + var opacity = (typeof obj.opacity !== "undefined") ? obj.opacity : 1; + opacity = Math.round(opacity * 100); + + var input = document.createElement("input"); + input.id = this._addUID("GPopacityValueDiv_ID_" + obj.id); + input.type = "range"; + input.value = opacity; + + // add event for opacity change + var context = this; + if (input.addEventListener) { + input.addEventListener( + "change", + function (e) { + context._onChangeLayerOpacity(e); + } + ); + } else if (input.attachEvent) { + // internet explorer + input.attachEvent( + "onchange", + function (e) { + context._onChangeLayerOpacity(e); + } + ); + } + + if (input.addEventListener) { + input.addEventListener( + "input", + function (e) { + context._onChangeLayerOpacity(e); + } + ); + } else if (input.attachEvent) { + // internet explorer + input.attachEvent( + "oninput", + function (e) { + context._onChangeLayerOpacity(e); + } + ); + } + + divO.appendChild(input); + + // Valeur d'opacité + var divC = document.createElement("div"); + divC.id = this._addUID("GPopacityValueDiv_ID_" + obj.id); + divC.className = "GPlayerOpacityValue"; + + var span = document.createElement("span"); + span.id = this._addUID("GPopacityValue_ID_" + obj.id); + span.innerHTML = opacity + "%"; + + divC.appendChild(span); + + list.push(divO); + list.push(divC); + + return list; + }, + + // ################################################################### // + // ############################ Layer info ########################### // + // ################################################################### // + + /** + * Creation du container du layer info (DOM) + * + * TODO GPlayerInfoPopup : ??? + * TODO GPlayerInfoLink : mettre en forme les échelles ! + * + * @param {Object} obj - options de la couche à ajouter dans le layer switcher + * + * @returns {DOMElement} container + */ + _createContainerLayerInfoElement : function (obj) { + var container = document.createElement("div"); + container.id = this._addUID("GPlayerInfoContent"); + + var title = document.createElement("div"); + title.id = this._addUID("GPlayerInfoTitle"); + title.innerHTML = obj.title; + container.appendChild(title); + + if (obj.quicklookUrl) { + var quick = document.createElement("div"); + quick.id = this._addUID("GPlayerInfoQuicklook"); + quick.title = "Afficher un aperçu de la couche"; + var refquick = document.createElement("a"); + refquick.href = obj.quicklookUrl; + refquick.appendChild(quick); + container.appendChild(refquick); + } + + var close = document.createElement("div"); + close.id = this._addUID("GPlayerInfoClose"); + close.title = "Fermer la fenêtre"; + + var self = this; + /** Call event function on close click */ + var onCloseClick = function () { + document.getElementById(self._addUID("GPlayerInfoPanel")).className = "GPlayerInfoPanelClosed"; + var layers = document.getElementsByClassName("GPlayerInfoOpened"); + for (var i = 0; i < layers.length; i++) { + layers[i].className = "GPlayerInfo"; + } + }; + if (close.addEventListener) { + close.addEventListener("click", onCloseClick); + } else if (close.attachEvent) { + // internet explorer + close.attachEvent("onclick", onCloseClick); + } + container.appendChild(close); + + var desc = document.createElement("div"); + desc.id = this._addUID("GPlayerInfoDescription"); + desc.innerHTML = obj.description; + container.appendChild(desc); + + if (obj.metadata) { + var mtd = document.createElement("div"); + mtd.id = this._addUID("GPlayerInfoMetadata"); + + var mtdtitle = document.createElement("div"); + mtdtitle.className = "GPlayerInfoSubtitle"; + mtdtitle.innerHTML = "Métadonnées"; + mtd.appendChild(mtdtitle); + + for (var i = 0; i < obj.metadata.length; i++) { + var urlmtd = obj.metadata[i].url; + + var mtdlink = document.createElement("div"); + mtdlink.className = "GPlayerInfoLink"; + + var refmtd = document.createElement("a"); + refmtd.href = urlmtd; + refmtd.innerHTML = urlmtd; + mtdlink.appendChild(refmtd); + mtd.appendChild(mtdlink); + } + + if (obj.metadata.length !== 0) { + container.appendChild(mtd); + } + } + + if (obj.legends) { + var lgd = document.createElement("div"); + lgd.id = this._addUID("GPlayerInfoLegend"); + + var lgdtitle = document.createElement("div"); + lgdtitle.className = "GPlayerInfoSubtitle"; + lgdtitle.innerHTML = "Légende"; + lgd.appendChild(lgdtitle); + + var legends = {}; + var maxScale = obj.maxScaleDenominator || 560000000; + + // on crée un tableau temporaire pour ordonner les légendes selon le dénominateur d'échelle + for (var k = 0; k < obj.legends.length; k++) { + var minScale = obj.legends[k].minScaleDenominator; + if (minScale) { + var s = minScale.toString(); + minScale = Math.round(parseInt(s.substring(0, 3), 10) / 10) * Math.pow(10, s.length - 2); + } else { + minScale = 270; + } + legends[minScale] = obj.legends[k]; + } + + for (var scale in legends) { + if (legends.hasOwnProperty(scale)) { + var urllgd = legends[scale].url; + // on n'affiche pas les légendes pointant vers "nolegend.jpg" + if (typeof urllgd === "string" && urllgd.toLowerCase().indexOf("nolegend.jpg") === -1) { + // TODO GPlayerInfoPopup + var lgdlink = document.createElement("div"); + lgdlink.className = "GPlayerInfoLink"; + + maxScale = legends[scale].maxScaleDenominator || maxScale; + + var reflgd = document.createElement("a"); + reflgd.href = urllgd; + reflgd.innerHTML = "Du 1/" + scale + " au 1/" + maxScale; + lgdlink.appendChild(reflgd); + lgd.appendChild(lgdlink); + } else { + delete legends[scale]; + } + } + } + + if (Object.keys(legends).length !== 0) { + container.appendChild(lgd); + } + } + + return container; + } +}; + +export default LayerSwitcherDOM; diff --git a/src/Common-review/Controls/LocationSelectorDOM.js b/src/Common-review/Controls/LocationSelectorDOM.js new file mode 100644 index 000000000..ea03d8edb --- /dev/null +++ b/src/Common-review/Controls/LocationSelectorDOM.js @@ -0,0 +1,484 @@ +import ID from "../Utils/SelectorID"; +import Logger from "../../Common/Utils/LoggerByDefault"; + +var logger = Logger.getLogger("LocationSelectorDOM"); + +var LocationSelectorDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.className = this._addUID("GPlocationPoint"); // ceci permet de gerer les groupes de points ! + container.className += " GPwidget"; + return container; + }, + + /** + * Create Container Point + * see event ! + * + * @param {Number} id - tag ID + * @param {Number} display - display + * @returns {DOMElement} DOM element + */ + _createLocationPointElement : function (id, display) { + var div = document.createElement("div"); + div.id = this._addUID("GPlocationPoint_" + id); + div.className = (display) ? "GPflexInput GPlocationStageFlexInput" : "GPflexInput GPlocationStageFlexInputHidden"; + div.style.cssText = ""; + + return div; + }, + + /** + * Create Container Point + * see event ! + * + * @param {Number} id - tag ID + * @param {String} text - label + * @returns {DOMElement} DOM element + */ + _createLocationPointLabelElement : function (id, text) { + // contexte d'execution + var self = this; + + var labelOrigin = document.createElement("label"); + labelOrigin.id = this._addUID("GPlocationOriginLabel_" + id); + labelOrigin.htmlFor = "GPlocationOrigin_" + id; + labelOrigin.innerHTML = text; + labelOrigin.addEventListener("click", function (e) { + var i = ID.index(this.id); + var points = document.getElementsByClassName(self._addUID("GPlocationPoint")); + for (var j = 0; j < points.length; j++) { + var tag = points[j].childNodes[0].id; + var id = ID.index(tag); + document.getElementById(self._addUID("GPlocationPoint_" + id)).style.cssText = ""; + } + document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).value = ""; + document.getElementById(self._addUID("GPlocationOrigin_" + i)).value = ""; + document.getElementById(self._addUID("GPlocationPoint_" + i)).style.cssText = ""; + document.getElementById(self._addUID("GPlocationOriginPointer_" + i)).checked = false; + document.getElementById(self._addUID("GPlocationOrigin_" + i)).className = "GPlocationOriginVisible"; + document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).className = "GPlocationOriginHidden"; + if (document.getElementById(self._addUID("GPlocationStageRemove_" + i))) { + document.getElementById(self._addUID("GPlocationStageRemove_" + i)).className = "GPlocationStageRemove"; + } + if (document.getElementById(self._addUID("GPlocationStageAdd"))) { + document.getElementById(self._addUID("GPlocationStageAdd")).className = ""; + } + // document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).disabled = true; + self.onLocationClearPointClick(e); + }); + + return labelOrigin; + }, + + /** + * Create Input AutoComplete Point tag + * + * @param {Number} id - tag ID + * @returns {DOMElement} DOM element + */ + _createLocationAutoCompleteteInputElement : function (id) { + // contexte d'execution + var self = this; + + var inputOrigin = document.createElement("input"); + inputOrigin.id = this._addUID("GPlocationOrigin_" + id); + inputOrigin.className = "GPlocationOriginVisible"; + inputOrigin.type = "text"; + inputOrigin.placeholder = "Saisir une adresse"; + inputOrigin.autocomplete = "off"; + inputOrigin.addEventListener("keyup", function (e) { + var charCode = e.which || e.keyCode; + if (charCode === 13 || charCode === 10 || charCode === 38 || charCode === 40) { + return; + } + + var i = ID.index(this.id); + if (document.getElementById(self._addUID("GPlocationOrigin_" + i)).value.length > 2) { + document.getElementById(self._addUID("GPlocationAutoCompleteList_" + i)).style.display = "block"; + } else { + document.getElementById(self._addUID("GPlocationAutoCompleteList_" + i)).style.display = "none"; + } + // gestionnaire d'evenement : + // on récupère la valeur de saisie pour une requête sur le service d'autocompletion. + // le resultat de la requête nous permet de recuperer les coordonnées du point... + self.onAutoCompleteSearchText(e); + }); + + inputOrigin.addEventListener("keydown", function (e) { + var charCode = e.which || e.keyCode; + + var container = document.getElementById(self._addUID("GPlocationAutoCompleteList_" + id)); + + // si aucun container !? + if (!container) { + return; + } + + var curr = container.getElementsByClassName("GPautoCompleteProposal current"); + var list = container.getElementsByClassName("GPautoCompleteProposal"); + + // si aucune suggestion, on ne va pas plus loin ! + var length = list.length; + if (!length) { + return; + } + + var current = null; + + // si aucun item courant, on prend le 1er ! + if (!curr.length) { + current = list[0]; + current.className = "GPautoCompleteProposal current"; + current.style.color = "#000000"; + current.style["background-color"] = "#CEDBEF"; + return; + } else { + current = curr[0]; + } + + var index = parseInt(ID.index(current.id), 10); + var next = (index === length - 1) ? list[0] : list[index + 1]; + var prev = (index === 0) ? list[length - 1] : list[index - 1]; + + current.style["background-color"] = ""; + current.style.color = ""; + prev.style["background-color"] = ""; + prev.style.color = ""; + next.style["background-color"] = ""; + next.style.color = ""; + + switch (charCode) { + case 38: // arrow up + logger.log("arrow up"); + current.className = "GPautoCompleteProposal"; + prev.className = "GPautoCompleteProposal current"; + prev.style.color = "#000000"; + prev.style["background-color"] = "#CEDBEF"; + break; + case 40: // arrow down + logger.log("arrow down"); + current.className = "GPautoCompleteProposal"; + next.className = "GPautoCompleteProposal current"; + next.style.color = "#000000"; + next.style["background-color"] = "#CEDBEF"; + break; + case 13: // enter + logger.log("enter"); + current.click(e); + break; + } + + current.focus(); + }); + + return inputOrigin; + }, + + /** + * Create Input Coordinate Point tag + * + * @param {Number} id - tag ID + * @returns {DOMElement} DOM element + */ + _createLocationCoordinateInputElement : function (id) { + // contexte d'execution + var self = this; + + var inputOriginCoord = document.createElement("input"); + inputOriginCoord.id = this._addUID("GPlocationOriginCoords_" + id); + inputOriginCoord.className = "GPlocationOriginHidden"; + inputOriginCoord.type = "text"; + inputOriginCoord.disabled = false; + inputOriginCoord.addEventListener("click", function () { + var i = ID.index(this.id); + document.getElementById(self._addUID("GPlocationOriginLabel_" + i)).click(); + }); + return inputOriginCoord; + }, + + /** + * Create Show Pointer tag + * + * @param {Number} id - tag ID + * @returns {DOMElement} DOM element + */ + _createLocationPointerShowInputElement : function (id) { + var inputOriginPointer = document.createElement("input"); + inputOriginPointer.id = this._addUID("GPlocationOriginPointer_" + id); + inputOriginPointer.type = "checkbox"; + return inputOriginPointer; + }, + + /** + * Create Input Pointer tag + * + * @param {Number} id - tag ID + * @returns {DOMElement} DOM element + */ + _createLocationPointerInputElement : function (id) { + // contexte d'execution + var self = this; + + var labelOriginPointer = document.createElement("label"); + labelOriginPointer.id = this._addUID("GPlocationOriginPointerImg_" + id); + labelOriginPointer.htmlFor = "GPlocationOriginPointer_" + id; + labelOriginPointer.className = "GPlocationOriginPointerImg"; + labelOriginPointer.title = "Pointer un lieu sur la carte"; + labelOriginPointer.addEventListener("click", function (e) { + e.preventDefault(); + e.stopPropagation(); + var i = ID.index(this.id); + var points = document.getElementsByClassName(self._addUID("GPlocationPoint")); + var j; + var tag; + var id; + for (j = 0; j < points.length; j++) { + tag = points[j].childNodes[0].id; + id = ID.index(tag); + if (i !== id) { + document.getElementById(self._addUID("GPlocationOriginPointer_" + id)).checked = false; + if (document.getElementById(self._addUID("GPlocationOriginCoords_" + id)).value === "Pointer un lieu sur la carte") { + document.getElementById(self._addUID("GPlocationOriginCoords_" + id)).value = ""; + document.getElementById(self._addUID("GPlocationOrigin_" + id)).className = "GPlocationOriginVisible"; + document.getElementById(self._addUID("GPlocationOriginCoords_" + id)).className = "GPlocationOriginHidden"; + } + } + } + if (document.getElementById(self._addUID("GPlocationOriginPointer_" + i)).checked) { + document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).value = ""; + for (j = 0; j < points.length; j++) { + tag = points[j].childNodes[0].id; + id = ID.index(tag); + document.getElementById(self._addUID("GPlocationPoint_" + id)).style.cssText = ""; + } + if (document.getElementById(self._addUID("GPlocationStageRemove_" + i))) { + document.getElementById(self._addUID("GPlocationStageRemove_" + i)).className = "GPlocationStageRemove"; + } + if (document.getElementById(self._addUID("GPlocationStageAdd"))) { + document.getElementById(self._addUID("GPlocationStageAdd")).className = ""; + } + document.getElementById(self._addUID("GPlocationOriginPointer_" + i)).checked = false; + document.getElementById(self._addUID("GPlocationOrigin_" + i)).className = "GPlocationOriginVisible"; + document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).className = "GPlocationOriginHidden"; + } else { + document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).value = "Pointer un lieu sur la carte"; + for (j = 0; j < points.length; j++) { + tag = points[j].childNodes[0].id; + id = ID.index(tag); + if (i === id) { + document.getElementById(self._addUID("GPlocationPoint_" + id)).style.cssText = ""; + } else { + document.getElementById(self._addUID("GPlocationPoint_" + id)).style.display = "none"; + } + } + if (document.getElementById(self._addUID("GPlocationStageRemove_" + i))) { + document.getElementById(self._addUID("GPlocationStageRemove_" + i)).className = "GPlocationOriginHidden"; + } + if (document.getElementById(self._addUID("GPlocationStageAdd"))) { + document.getElementById(self._addUID("GPlocationStageAdd")).className = "GPlocationOriginHidden"; + } + document.getElementById(self._addUID("GPlocationOriginPointer_" + i)).checked = true; + document.getElementById(self._addUID("GPlocationOrigin_" + i)).className = "GPlocationOriginHidden"; + document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).className = "GPlocationOriginVisible"; + document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).disabled = true; + } + // gestionnaire d'evenement : + // on stocke la valeur du point, utilisée pour la requête sur le service de calcul d'itiniraire + self.onActivateMapPointClick(e); + }); + + return labelOriginPointer; + }, + + /** + * Create Remove Point tag + * see event ! + * + * @param {Number} id - tag ID + * @returns {DOMElement} DOM element + */ + _createLocationRemovePointElement : function (id) { + // contexte d'execution + var self = this; + + var divRm = document.createElement("div"); + divRm.id = this._addUID("GPlocationStageRemove_" + id); + divRm.className = "GPlocationStageRemove"; + divRm.title = "Supprimer l'étape"; + divRm.addEventListener("click", function (e) { + var points = document.getElementsByClassName(self._addUID("GPlocationPoint")); + var last = points.length - 1; + var start = points[0].childNodes[0].id; + var end = points[last].childNodes[0].id; + + var startID = ID.index(start); + var endID = ID.index(end); + + if (id !== startID && id !== endID) { + var i = ID.index(this.id); + document.getElementById(self._addUID("GPlocationPoint_" + i)).className = "GPflexInput GPlocationStageFlexInputHidden"; + document.getElementById(self._addUID("GPlocationOrigin_" + i)).value = ""; + document.getElementById(self._addUID("GPlocationOrigin_" + i)).className = "GPlocationOriginVisible"; + document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).value = ""; + document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).className = "GPlocationOriginHidden"; + document.getElementById(self._addUID("GPlocationStageAdd")).style.display = ""; + // Moving up exclusions picto + // var exclusionsPictoTop = document.getElementById(self._addUID("GPshowLocationExclusionsPicto")).style.top; + // document.getElementById(self._addUID("GPshowLocationExclusionsPicto")).style.top = (parseInt(exclusionsPictoTop) - 33).toString() + "px"; + + // gestionnaire d'evenement : + // on supprime le point, utilisé pour la requête sur le service d'itiniraire + self.onLocationRemovePointClick(e); + } + }); + + return divRm; + }, + + /** + * Create Add Point tag + * see event ! + * + * @returns {DOMElement} DOM element + */ + _createLocationAddPointElement : function () { + // contexte d'execution + var self = this; + + var divAdd = document.createElement("div"); + divAdd.id = this._addUID("GPlocationStageAdd"); + divAdd.title = "Ajouter une étape"; + divAdd.addEventListener("click", function (e) { + var lastStage = 1; + var nbStages = 0; + var points = document.getElementsByClassName(self._addUID("GPlocationPoint")); + for (var i = 1; i < points.length - 1; i++) { + var tag = points[i].childNodes[0].id; + var id = ID.index(tag); + if (document.getElementById(self._addUID("GPlocationPoint_" + id))) { + if (document.getElementById(self._addUID("GPlocationPoint_" + id)).className === "GPflexInput GPlocationStageFlexInputHidden") { + if (lastStage === 1) { + lastStage = id; + } + } else { + nbStages++; + } + } + } + // FIXME algo à revoir : lastStage = id hors si id = 300 sur 3 points !? + if (lastStage < points.length) { + document.getElementById(self._addUID("GPlocationPoint_" + lastStage)).className = "GPflexInput GPlocationStageFlexInput"; + // Moving down exclusions picto + // var exclusionsPictoTop = document.getElementById(self._addUID("GPshowLocationExclusionsPicto")).style.top; + // document.getElementById(self._addUID("GPshowLocationExclusionsPicto")).style.top = (parseInt(exclusionsPictoTop) + 33).toString() + "px"; + } + if (nbStages === 4) { + document.getElementById(self._addUID("GPlocationStageAdd")).style.display = "none"; + } + // gestionnaire d'evenement : + // on ajoute le point, utilisé pour la requête sur le service d'itiniraire + self.onLocationAddPointClick(e); + }); + + return divAdd; + }, + + /** + * Create Results autocompletion to the point + * see event! + * + * @param {Number} id - tag ID + * @returns {DOMElement} DOM element + */ + _createLocationAutoCompleteResultElement : function (id) { + // contexte d'execution + var self = this; + + var div = document.createElement("div"); + div.id = this._addUID("GPlocationAutoCompleteList_" + id); + div.className = "GPadvancedAutoCompleteList"; + + if (div.addEventListener) { + div.addEventListener("click", function (e) { + self.onAutoCompletedResultsItemClick(e); + document.getElementById(self._addUID("GPlocationAutoCompleteList_" + id)).style.display = "none"; + }, false); + } else if (div.attachEvent) { + div.attachEvent("onclick", function (e) { + self.onAutoCompletedResultsItemClick(e); + document.getElementById(self._addUID("GPlocationAutoCompleteList_" + id)).style.display = "none"; + }); + } + + return div; + }, + + /** + * Autocompletion result to a point. + * Proposals are dynamically filled in Javascript by autocomplete service + * + * TODO formaliser le contenu des reponse + * + * @param {Number} id - tag ID + * @param {Object} location - suggested location result + * @param {Number} n - number of the point + */ + _createLocationAutoCompletedLocationElement : function (id, location, n) { + var container = document.getElementById(this._addUID("GPlocationAutoCompleteList_" + id)); + + var div = document.createElement("div"); + div.id = this._addUID("AutoCompletedLocation_" + n); + div.className = "GPautoCompleteProposal"; + div.innerHTML = location.fullText; + + container.appendChild(div); + }, + + /** + * Display Coordinate + * @param {String} value - a Coordinate + */ + GPdisplayCoordinate : function (value) { + var points = document.getElementsByClassName(this._addUID("GPlocationPoint")); + for (var i = 0; i < points.length; i++) { + var tag = points[i].childNodes[0].id; + var id1 = ID.index(tag); + if (document.getElementById(this._addUID("GPlocationOriginPointer_" + id1)).checked) { + document.getElementById(this._addUID("GPlocationOriginCoords_" + id1)).value = value; + document.getElementById(this._addUID("GPlocationOriginCoords_" + id1)).disabled = false; + for (var j = 0; j < points.length; j++) { + tag = points[j].childNodes[0].id; + var id2 = ID.index(tag); + document.getElementById(this._addUID("GPlocationPoint_" + id2)).style.cssText = ""; + if (document.getElementById(this._addUID("GPlocationStageRemove_" + id2))) { + document.getElementById(this._addUID("GPlocationStageRemove_" + id2)).className = "GPlocationStageRemove"; + } + } + document.getElementById(this._addUID("GPlocationOriginPointer_" + id1)).checked = false; + if (document.getElementById(this._addUID("GPlocationStageAdd"))) { + document.getElementById(this._addUID("GPlocationStageAdd")).className = ""; + } + return; + } + } + } +}; + +export default LocationSelectorDOM; diff --git a/src/Common-review/Controls/MeasureAreaDOM.js b/src/Common-review/Controls/MeasureAreaDOM.js new file mode 100644 index 000000000..900a882f7 --- /dev/null +++ b/src/Common-review/Controls/MeasureAreaDOM.js @@ -0,0 +1,80 @@ +var MeasureAreaDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPmeasureArea"); + container.className = "GPwidget"; + return container; + }, + + // ################################################################### // + // ################### Methods of main container ##################### // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing + * + * @returns {DOMElement} DOM element + */ + _createShowMeasureAreaElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowMeasureArea"); + input.type = "checkbox"; + return input; + }, + + /** + * Show control + * see event ! + * + * @returns {DOMElement} DOM element + */ + _createShowMeasureAreaPictoElement : function () { + // contexte d'execution + var context = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowMeasureAreaPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowMeasureArea"); + label.title = "Mesurer une surface"; + + // gestionnaire d'evenement : + // on ouvre le menu de saisie... + // L'ouverture/Fermeture permet de faire le menage + // (reinitialisation) + if (label.addEventListener) { + label.addEventListener("click", function (e) { + context.onShowMeasureAreaClick(e); + }); + } else if (label.attachEvent) { + label.attachEvent("onclick", function (e) { + context.onShowMeasureAreaClick(e); + }); + } + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowMeasureAreaOpen"); + spanOpen.className = "GPshowAdvancedToolOpen"; + label.appendChild(spanOpen); + + return label; + } +}; + +export default MeasureAreaDOM; diff --git a/src/Common-review/Controls/MeasureAzimuthDOM.js b/src/Common-review/Controls/MeasureAzimuthDOM.js new file mode 100644 index 000000000..84f003e83 --- /dev/null +++ b/src/Common-review/Controls/MeasureAzimuthDOM.js @@ -0,0 +1,80 @@ +var MeasureAzimuthDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPmeasureAzimuth"); + container.className = "GPwidget"; + return container; + }, + + // ################################################################### // + // ################### Methods of main container ##################### // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing + * + * @returns {DOMElement} DOM element + */ + _createShowMeasureAzimuthElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowMeasureAzimuth"); + input.type = "checkbox"; + return input; + }, + + /** + * Show control + * see event ! + * + * @returns {DOMElement} DOM element + */ + _createShowMeasureAzimuthPictoElement : function () { + // contexte d'execution + var context = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowMeasureAzimuthPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowMeasureAzimuth"); + label.title = "Mesurer un azimut"; + + // gestionnaire d'evenement : + // on ouvre le menu de saisie... + // L'ouverture/Fermeture permet de faire le menage + // (reinitialisation) + if (label.addEventListener) { + label.addEventListener("click", function (e) { + context.onShowMeasureAzimuthClick(e); + }); + } else if (label.attachEvent) { + label.attachEvent("onclick", function (e) { + context.onShowMeasureAzimuthClick(e); + }); + } + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowMeasureAzimuthOpen"); + spanOpen.className = "GPshowAdvancedToolOpen"; + label.appendChild(spanOpen); + + return label; + } +}; + +export default MeasureAzimuthDOM; diff --git a/src/Common-review/Controls/MeasureLengthDOM.js b/src/Common-review/Controls/MeasureLengthDOM.js new file mode 100644 index 000000000..7be6593cf --- /dev/null +++ b/src/Common-review/Controls/MeasureLengthDOM.js @@ -0,0 +1,80 @@ +var MeasureLengthDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPmeasureLength"); + container.className = "GPwidget"; + return container; + }, + + // ################################################################### // + // ################### Methods of main container ##################### // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing + * + * @returns {DOMElement} DOM element + */ + _createShowMeasureLengthElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowMeasureLength"); + input.type = "checkbox"; + return input; + }, + + /** + * Show control + * see event ! + * + * @returns {DOMElement} DOM element + */ + _createShowMeasureLengthPictoElement : function () { + // contexte d'execution + var context = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowMeasureLengthPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowMeasureLength"); + label.title = "Mesurer une distance"; + + // gestionnaire d'evenement : + // on ouvre le menu de saisie... + // L'ouverture/Fermeture permet de faire le menage + // (reinitialisation) + if (label.addEventListener) { + label.addEventListener("click", function (e) { + context.onShowMeasureLengthClick(e); + }); + } else if (label.attachEvent) { + label.attachEvent("onclick", function (e) { + context.onShowMeasureLengthClick(e); + }); + } + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowMeasureLengthOpen"); + spanOpen.className = "GPshowAdvancedToolOpen"; + label.appendChild(spanOpen); + + return label; + } +}; + +export default MeasureLengthDOM; diff --git a/src/Common-review/Controls/MeasureToolBoxDOM.js b/src/Common-review/Controls/MeasureToolBoxDOM.js new file mode 100644 index 000000000..ed1949e0c --- /dev/null +++ b/src/Common-review/Controls/MeasureToolBoxDOM.js @@ -0,0 +1,102 @@ +var MeasureToolBoxDOM = { + + _toolboxId : "GPtoolbox-measure-main", + _buttonId : "GPtoolbox-measure-button", + _widgetId : "GPtoolbox-measure-widget", + + /** + * get toolBox ID + * @param {Number} uid - uid + * @returns {String} id selector unique + */ + getToolBoxID : function (uid) { + return (uid) ? this._toolboxId + "-" + uid : this._toolboxId; + }, + + /** + * get button ID + * @param {Number} uid - uid + * @returns {String} id selector unique + */ + getButtonID : function (uid) { + return (uid) ? this._buttonId + "-" + uid : this._buttonId; + }, + + /** + * get toolBox Container for widget + * @param {Number} uid - uid + * @returns {String} id selector unique + */ + getWidgetID : function (uid) { + return (uid) ? this._widgetId + "-" + uid : this._widgetId; + }, + + /** + * Main container (DOM) + * @param {Number} uid - uid + * @returns {DOMElement} DOM element + */ + _createToolBoxContainerElement : function (uid) { + //
+ // + //
+ // + //
+ //
+ var container = document.createElement("div"); + container.id = this.getToolBoxID(uid); + container.className = "GPshowAdvancedToolPicto"; + + var button = document.createElement("button"); + button.id = this.getButtonID(uid); + var self = this; + button.addEventListener("click", function () { + this.blur(); // permet de perdre le focus ! + var widget = document.getElementById(self.getWidgetID(uid)); + if (widget.style.display === "block") { + widget.style.display = "none"; + } else { + widget.style.display = "block"; + } + }); + container.appendChild(button); + + var widget = document.createElement("div"); + widget.id = this.getWidgetID(uid); + widget.addEventListener("click", function () { + + /* + e.preventDefault(); + + // FIXME desactiver tous les outils sur + // l'ouverture/fermeture de la toolbox ? + + var current = e.target.parentNode.getAttribute("for"); + var widgets = this.querySelectorAll("div > input"); + for (var i = 0; i < widgets.length; i++) { + var id = widgets[i].id; + + if (document.getElementById(id) && + document.getElementById(id).checked && + document.querySelector("#" + id + " + label")) { + document.querySelector("#" + id + " + label").click(); + // document.getElementById(id).checked = true; + } + + if (current === id && widgets[i].checked) { + widgets[i].checked = false; + } else if (current === id && !widgets[i].checked) { + widgets[i].checked = true; + } + } + */ + + }, false); + + container.appendChild(widget); + + return container; + } +}; + +export default MeasureToolBoxDOM; diff --git a/src/Common-review/Controls/MiniGlobeDOM.js b/src/Common-review/Controls/MiniGlobeDOM.js new file mode 100644 index 000000000..f03985d4e --- /dev/null +++ b/src/Common-review/Controls/MiniGlobeDOM.js @@ -0,0 +1,28 @@ +var MiniGlobeDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPminiglobeContainer"); + container.className = "GPwidget"; + container.style.width = "100px"; + container.style.height = "100px"; + return container; + } +}; + +export default MiniGlobeDOM; diff --git a/src/Common-review/Controls/MousePositionDOM.js b/src/Common-review/Controls/MousePositionDOM.js new file mode 100644 index 000000000..e24ce7352 --- /dev/null +++ b/src/Common-review/Controls/MousePositionDOM.js @@ -0,0 +1,940 @@ +var MousePositionDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPmousePosition"); + container.className = "GPwidget"; + return container; + }, + + // ################################################################### // + // ################### Methods of main container ##################### // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing + * + * @returns {DOMElement} DOM element + */ + _createShowMousePositionElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowMousePosition"); + input.type = "checkbox"; + return input; + }, + + /** + * Show mouse position control + * @param {Boolean} isDesktop - specifies if the support is desktop or tactile + * + * @returns {DOMElement} DOM element + */ + _createShowMousePositionPictoElement : function (isDesktop) { + // contexte d'execution + var self = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowMousePositionPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowMousePosition"); + label.title = "Afficher les coordonnées du curseur"; + + // FIXME detection disponible dans le JS ! + // Detection : test for desktop or tactile + // var isDesktop = true; + // var userAgent = window.navigator.userAgent.toLowerCase(); + // if (userAgent.indexOf("iphone") !== -1 || + // userAgent.indexOf("ipod") !== -1 || + // userAgent.indexOf("ipad") !== -1 || + // userAgent.indexOf("android") !== -1 || + // userAgent.indexOf("mobile") !== -1 || + // userAgent.indexOf("blackberry") !== -1 || + // userAgent.indexOf("tablet") !== -1 || + // userAgent.indexOf("phone") !== -1 || + // userAgent.indexOf("touch") !== -1 ) { + // isDesktop = false; + // } + // if (userAgent.indexOf("msie") !== -1 || + // userAgent.indexOf("trident") !== -1) { + // isDesktop = true; + // } + + // Show map center localisation if panel opened and tactile support + label.addEventListener("click", function (e) { + var mapCenterClass = ""; + if (!document.getElementById(self._addUID("GPshowMousePosition")).checked && !isDesktop) { + mapCenterClass = "GPmapCenterVisible"; + } + document.getElementById("GPmapCenter").className = mapCenterClass; + self.onShowMousePositionClick(e); + }); + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowMousePositionOpen"); + spanOpen.className = "GPshowAdvancedToolOpen"; + label.appendChild(spanOpen); + + return label; + }, + + /** + * mouse position panel + * + * @returns {DOMElement} DOM element + */ + _createMousePositionPanelElement : function () { + var panel = document.createElement("div"); + panel.id = this._addUID("GPmousePositionPanel"); + panel.className = "GPpanel"; + + // FIXME on decompose la fonction pour les besoins du controle, + // on ajoutera ces childs à la main... + // div.appendChild(this._createMousePositionPanelHeaderElement()); + // div.appendChild(this._createMousePositionPanelBasicElement()); + // div.appendChild(this._createShowMousePositionSettingsElement()); + // div.appendChild(this._createMousePositionSettingsElement()); + + return panel; + }, + + /** + * Map center localisation (tactile use) + * + * @returns {DOMElement} container + */ + _createMapCenter : function () { + var div = document.createElement("div"); + div.id = "GPmapCenter"; + div.className = ""; + return div; + }, + + // ################################################################### // + // ####################### Panel container ########################### // + // ################################################################### // + + /** + * @returns {DOMElement} container + */ + _createMousePositionPanelHeaderElement : function () { + var container = document.createElement("div"); + container.className = "GPpanelHeader"; + + var divTitle = document.createElement("div"); + divTitle.className = "GPpanelTitle"; + divTitle.innerHTML = "Coordonnées"; + container.appendChild(divTitle); + + var divClose = document.createElement("div"); + divClose.id = "GPmousePositionPanelClose"; + divClose.className = "GPpanelClose"; + divClose.title = "Fermer le panneau"; + + // Link panel close / visibility checkbox + var self = this; + if (divClose.addEventListener) { + divClose.addEventListener("click", function () { + document.getElementById(self._addUID("GPshowMousePositionPicto")).click(); + }, false); + } else if (divClose.attachEvent) { + divClose.attachEvent("onclick", function () { + document.getElementById(self._addUID("GPshowMousePositionPicto")).click(); + }); + } + + container.appendChild(divClose); + + return container; + }, + + /** + * coordinate panel + * @param {Boolean} [displayAltitude] - specifies if the altitude panel must be displayed + * @param {Boolean} [displayCoordinates] - specifies if the coordinates panel must be displayed + * @param {Boolean} [editCoordinates] - specifies if the coordinates edition is allowed + * @param {Boolean} [currentProjectionUnits] - specifies if the current projection units + * + * FIXME + * call this._createMousePositionPanelBasicCoordinateElement + * call this._createMousePositionPanelBasicAltitudeElement + * + * @returns {DOMElement} DOM element + */ + _createMousePositionPanelBasicElement : function (displayAltitude, displayCoordinates, editCoordinates, currentProjectionUnits) { + // default Values + displayAltitude = (typeof displayAltitude === "undefined") ? true : displayAltitude; + displayCoordinates = (typeof displayCoordinates === "undefined") ? true : displayCoordinates; + editCoordinates = (typeof editCoordinates === "undefined") ? false : editCoordinates; + + var container = document.createElement("div"); + container.id = this._addUID("GPmousePositionBasicPanel"); + + // FIXME on devrait decomposer la fonction pour les besoins du controle, + // on ajoutera ces childs à la main... + container.appendChild(this._createMousePositionPanelBasicCoordinateElement(displayCoordinates, editCoordinates, currentProjectionUnits)); + container.appendChild(this._createMousePositionPanelEditToolsElement(editCoordinates)); + container.appendChild(this._createMousePositionPanelBasicAltitudeElement(displayAltitude)); + + return container; + }, + + /** + * create coordinate elements + * + * @param {String} coordType - ("Lon" ou "Lat") + * @param {Boolean} [editCoordinates=false] - specifies if the coordinates edition is allowed + * + * @returns {Array} list of DOM elements + */ + _createCoordinateElement : function (coordType, editCoordinates) { + var context = this; + + if (["Lon", "Lat"].indexOf(coordType) === -1) { + return []; + } + + var list = []; + var input = document.createElement("input"); + input.id = this._addUID("GPmousePosition" + coordType); + input.title = editCoordinates === true ? "Cliquer pour saisir des coordonnées" : ""; + input.readOnly = true; + + if (editCoordinates) { + input.addEventListener("click", function () { + context.onMousePositionEditModeClick(true); + }); + input.addEventListener("change", function (e) { + this.classList.remove("error"); + var valid = context.validateExtentCoordinate(coordType, this.value, e); + valid ? this.classList.remove("error") : this.classList.add("error"); + }); + } + list.push(input); + + var span = document.createElement("span"); + span.className = "GPmousePositionUnits"; + list.push(span); + + return list; + }, + + /** + * + * @param {String} coordType - ("Lon" ou "Lat") + * @param {Boolean} [editCoordinates=false] - specifies if the coordinates edition is allowed + * + * @returns {Array} list of DOM elements + */ + _createDMSCoordinateElement : function (coordType, editCoordinates) { + if (["Lon", "Lat"].indexOf(coordType) === -1) { + return []; + } + + var context = this; + + var list = []; + + var input = document.createElement("input"); + input.id = this._addUID("GPmousePosition" + coordType + "Degrees"); + input.className = "GPSexagesimal"; + input.setAttribute("name", "degrees"); + input.title = editCoordinates === true ? "Cliquer pour saisir des coordonnées" : ""; + input.readOnly = true; + input.dataset.min = 0; + input.dataset.max = (coordType === "Lon") ? 180 : 90; + if (editCoordinates) { + input.addEventListener("click", function () { + context.onMousePositionEditModeClick(true); + }); + input.addEventListener("change", function () { + this.classList.remove("error"); + var valid = context._checkDMSDegrees(coordType, this); + valid ? this.classList.remove("error") : this.classList.add("error"); + }); + } + list.push(input); + + var span = document.createElement("span"); + span.className = "GPmousePositionSexagesimalLabel"; + span.innerHTML = "°"; + list.push(span); + + var input1 = document.createElement("input"); + input1.id = this._addUID("GPmousePosition" + coordType + "Minutes"); + input1.className = "GPSexagesimal"; + input1.setAttribute("name", "minutes"); + input1.title = editCoordinates === true ? "Cliquer pour saisir des coordonnées" : ""; + input1.readOnly = true; + input1.dataset.min = 0; + input1.dataset.max = 59; + if (editCoordinates) { + input1.addEventListener("click", function () { + context.onMousePositionEditModeClick(true); + }); + input1.addEventListener("change", function () { + this.classList.remove("error"); + var valid = context._checkDMSElement(this); + valid ? this.classList.remove("error") : this.classList.add("error"); + }); + } + list.push(input1); + + var span1 = document.createElement("span"); + span1.className = "GPmousePositionSexagesimalLabel"; + span1.innerHTML = "'"; + list.push(span1); + + var input2 = document.createElement("input"); + input2.id = this._addUID("GPmousePosition" + coordType + "Seconds"); + input2.className = "GPSexagesimalsec"; + input2.setAttribute("name", "seconds"); + input2.title = editCoordinates === true ? "Cliquer pour saisir des coordonnées" : ""; + input2.readOnly = true; + input2.dataset.min = 0; + input2.dataset.max = 59; + if (editCoordinates) { + input2.addEventListener("click", function () { + context.onMousePositionEditModeClick(true); + }); + input2.addEventListener("change", function () { + this.classList.remove("error"); + var valid = context._checkDMSElement(this, true); + valid ? this.classList.remove("error") : this.classList.add("error"); + }); + } + list.push(input2); + + var span2 = document.createElement("span"); + span2.className = "GPmousePositionSexagesimalLabel"; + span2.innerHTML = "''"; + list.push(span2); + + var select = document.createElement("select"); + select.id = this._addUID("GPmousePosition" + coordType + "Direction"); + select.className = "GPmousePositionDirection"; + select.setAttribute("name", "direction"); + select.disabled = true; + + var option = document.createElement("option"); + option.value = (coordType === "Lon") ? "E" : "N"; + option.innerHTML = (coordType === "Lon") ? "E" : "N"; + select.appendChild(option); + + var option1 = document.createElement("option"); + option1.value = (coordType === "Lon") ? "O" : "S"; + option1.innerHTML = (coordType === "Lon") ? "O" : "S"; + select.appendChild(option1); + list.push(select); + + return list; + }, + + /** + * @param {Boolean} [display=false] - specifies if the coordinates panel must be displayed + * @param {Boolean} [editCoordinates] - specifies if the coordinates edition is allowed + * @param {Boolean} [currentProjectionUnits] - specifies if the current projection units + * + * @returns {DOMElement} container + */ + _createMousePositionPanelBasicCoordinateElement : function (display, editCoordinates, currentProjectionUnits) { + var div = document.createElement("div"); + div.id = this._addUID("GPmousePositionCoordinate"); + div.style.display = display ? "block" : "none"; + + // latitude + var divLat = document.createElement("div"); + + var spanLat = document.createElement("span"); + spanLat.className = "GPmousePositionLabel"; + spanLat.id = this._addUID("GPmousePositionLatLabel"); + spanLat.innerHTML = "Latitude : "; + divLat.appendChild(spanLat); + + var span = document.createElement("span"); + span.id = this._addUID("GPmousePositionLatCoordinate"); + + var arrayCoords; + if (currentProjectionUnits === "DMS") { + arrayCoords = this._createDMSCoordinateElement("Lat", editCoordinates); + } else { + arrayCoords = this._createCoordinateElement("Lat", editCoordinates); + } + for (var i = 0; i < arrayCoords.length; i++) { + span.appendChild(arrayCoords[i]); + } + divLat.appendChild(span); + div.appendChild(divLat); + + // longitude + var divLon = document.createElement("div"); + + var spanLon = document.createElement("span"); + spanLon.className = "GPmousePositionLabel"; + spanLon.id = this._addUID("GPmousePositionLonLabel"); + spanLon.innerHTML = "Longitude : "; + divLon.appendChild(spanLon); + + var span1 = document.createElement("span"); + span1.id = this._addUID("GPmousePositionLonCoordinate"); + + var arrayCoords1; + if (currentProjectionUnits === "DMS") { + arrayCoords1 = this._createDMSCoordinateElement("Lon", editCoordinates); + } else { + arrayCoords1 = this._createCoordinateElement("Lon", editCoordinates); + } + for (var j = 0; j < arrayCoords1.length; j++) { + span1.appendChild(arrayCoords1[j]); + } + divLon.appendChild(span1); + div.appendChild(divLon); + + return div; + }, + + /** + * @param {Boolean} [display=false] - specifies if the altitude panel must be displayed + * + * @returns {DOMElement} container + */ + _createMousePositionPanelBasicAltitudeElement : function (display) { + var div = document.createElement("div"); + div.id = this._addUID("GPmousePositionAltitude"); + div.style.display = display ? "block" : "none"; + + var spanLabel = document.createElement("span"); + spanLabel.className = "GPmousePositionLabel"; + spanLabel.innerHTML = "Altitude : "; + div.appendChild(spanLabel); + + var spanAlt = document.createElement("span"); + spanAlt.className = "GPmousePositionCoords"; + spanAlt.id = this._addUID("GPmousePositionAlt"); + spanAlt.innerHTML = "..."; + div.appendChild(spanAlt); + + var spanUnits = document.createElement("span"); + spanUnits.className = "GPmousePositionAltitudeUnits"; + spanUnits.innerHTML = "m"; + div.appendChild(spanUnits); + + return div; + }, + + /** + * @param {Boolean} [editCoordinates=false] - specifies if the coordinates edition is allowed + * + * @returns {DOMElement} container + */ + _createMousePositionPanelEditToolsElement : function (editCoordinates) { + var context = this; + + var div = document.createElement("div"); + div.className = "GPmousePositionPanelEditTools"; + div.id = this._addUID("GPmousePositionPanelEditTools"); + if (!editCoordinates) { + div.style.display = "none"; + } + + var span1 = document.createElement("span"); + span1.className = "GPmousePositionEditTool"; + span1.id = this._addUID("GPmousePositionLocate"); + span1.title = editCoordinates === true ? "Cliquer pour saisir des coordonnées" : ""; + if (editCoordinates) { + span1.addEventListener("click", function () { + context.onMousePositionEditModeLocateClick(); + }); + } + div.appendChild(span1); + + var span2 = document.createElement("span"); + span2.className = "GPmousePositionEditTool"; + span2.id = this._addUID("GPmousePositionCloseEdit"); + span2.title = "Quitter la saisie des coordonnées"; + span2.style.display = "none"; + if (editCoordinates) { + span2.addEventListener("click", function () { + context.onMousePositionEditModeClick(false); + }); + } + div.appendChild(span2); + + return div; + }, + + // ################################################################### // + // #################### Settings container ########################### // + // ################################################################### // + + /** + * @param {Boolean} [display=false] - specifies if the settings panel must be displayed + * + * @returns {DOMElement[]} array containing input and label elements + */ + _createShowMousePositionSettingsElement : function (display) { + var list = []; + + var context = this; + + var input = document.createElement("input"); + input.type = "checkbox"; + input.id = this._addUID("GPshowMousePositionSettings"); + + var label = document.createElement("label"); + label.id = this._addUID("GPshowMousePositionSettingsPicto"); + label.htmlFor = this._addUID("GPshowMousePositionSettings"); + label.title = "Réglages"; + label.className = "GPshowMoreOptionsImage GPshowMoreOptions GPshowMousePositionSettingsPicto"; // FIXME classname and id ? + label.style.display = display ? "block" : "none"; + if (label.addEventListener) { + label.addEventListener("click", function (e) { + if (typeof context.onShowMousePositionSettingsClick === "function") { + context.onShowMousePositionSettingsClick(e); + } + }, false); + } else if (label.attachEvent) { + label.attachEvent("onclick", function (e) { + if (typeof context.onShowMousePositionSettingsClick === "function") { + context.onShowMousePositionSettingsClick(e); + } + }); + } + + list.push(input); + list.push(label); + + return list; + }, + + /** + * settings panel + * @param {Boolean} [display=true] - specifies if the settings panel must be displayed + * + * FIXME + * don't call this._createMousePositionSettingsSystemsElement + * don't call this._createMousePositionSettingsUnitsElement + * + * @returns {DOMElement} DOM element + */ + _createMousePositionSettingsElement : function (display) { + var container = document.createElement("div"); + container.id = this._addUID("GPmousePositionSettings"); + container.style.display = (display === undefined || display) ? "block" : "none"; + + var span = document.createElement("span"); + span.className = "GPmousePositionSettingsLabel"; + span.innerHTML = "Système de référence"; + container.appendChild(span); + + // FIXME on decompose la fonction pour les besoins du controle, + // on ajoutera ces childs à la main... + // FIXME tableau statique ! + // var systems = [ + // { + // code : "GEOGRAPHIC", + // label : "Géographique" + // }, + // { + // code : "MERCATOR", + // label : "Mercator" + // }, + // { + // code : "LAMB93", + // label : "Lambert 93" + // }, + // { + // code : "LAMB2E", + // label : "Lambert II étendu" + // } + // ]; + // + // var selectSystem = this._createMousePositionSettingsSystemsElement(systems); + // + // container.appendChild(selectSystem); + + // FIXME on decompose la fonction pour les besoins du controle, + // on ajoutera ces childs à la main... + // FIXME tableau statique ! + // var units = [ + // { + // code : "DEC", + // label : "degrés décimaux", + // }, + // { + // code : "DMS", + // label : "degrés sexagésimaux", + // }, + // { + // code : "RAD", + // label : "radians", + // }, + // { + // code : "GON", + // label : "grades" + // } + // ]; + // + // var selectUnits = this._createMousePositionSettingsUnitsElement(units); + // + // container.appendChild(selectUnits); + + return container; + }, + + /** + * @param {Object[]} systems - list of systems + * + * @returns {DOMElement} DOM element select + */ + _createMousePositionSettingsSystemsElement : function (systems) { + // contexte d'execution + var context = this; + + var selectSystem = document.createElement("select"); + selectSystem.id = this._addUID("GPmousePositionProjectionSystem"); + selectSystem.className = "GPinputSelect GPmousePositionSettingsSelect"; + selectSystem.addEventListener("change", function (e) { + context.onMousePositionProjectionSystemChange(e); + }); + selectSystem.addEventListener("mouseover", function (e) { + // FIXME mettre une condition si target === option + if (e.target.nodeName !== "OPTION") { + context.onMousePositionProjectionSystemMouseOver(e); + } + }); + + for (var i = 0; i < systems.length; i++) { + var obj = systems[i]; + var option = document.createElement("option"); + option.value = obj.code; + option.text = obj.label || i; + // option.label = obj.label; + selectSystem.appendChild(option); + } + + return selectSystem; + }, + + /** + * @param {Object[]} units - list of units + * + * @returns {DOMElement} DOM element select + */ + _createMousePositionSettingsUnitsElement : function (units) { + // contexte d'execution + var context = this; + + var selectUnits = document.createElement("select"); + selectUnits.id = this._addUID("GPmousePositionProjectionUnits"); + selectUnits.className = "GPinputSelect GPmousePositionSettingsSelect"; + selectUnits.addEventListener("change", function (e) { + context.onMousePositionProjectionUnitsChange(e); + }); + + for (var j = 0; j < units.length; j++) { + var obj = units[j]; + var option = document.createElement("option"); + option.value = (obj.code) ? obj.code : j; + option.text = obj.label || j; + // option.label = obj.label; + selectUnits.appendChild(option); + } + + return selectUnits; + }, + + /** + * @param {String} [currentProjectionType="Metric"] - "Geographical" or "Metric" + */ + _resetLabelElements : function (currentProjectionType) { + // Changement des labels dans le formulaire de saisie + var spanLat = document.getElementById(this._addUID("GPmousePositionLatLabel")); + spanLat.innerHTML = currentProjectionType === "Geographical" ? "Latitude :" : "X :"; + + var spanLon = document.getElementById(this._addUID("GPmousePositionLonLabel")); + spanLon.innerHTML = currentProjectionType === "Geographical" ? "Longitude :" : "Y :"; + }, + + /** + * @param {String} currentProjectionUnits - projection units + */ + _resetUnitElements : function (currentProjectionUnits) { + var value = ""; + if (currentProjectionUnits === "M" || currentProjectionUnits === "KM") { + value = currentProjectionUnits.toLowerCase(); + } + + var elts = document.getElementsByClassName("GPmousePositionUnits"); + for (var e = 0; e < elts.length; e++) { + elts[e].innerHTML = value; + } + }, + + /** + * @method _resetCoordinateElements + * @param {Boolean} editCoordinates - edit coordinates option + * @param {String} currentProjectionType - current projection type + * @param {String} currentProjectionUnits - current projection unit + */ + _resetCoordinateElements : function (editCoordinates, currentProjectionType, currentProjectionUnits) { + // Suppression de tous les enfants de GPmousePositionLatCoordinate + var latElt = document.getElementById(this._addUID("GPmousePositionLatCoordinate")); + while (latElt.firstChild) { + latElt.removeChild(latElt.firstChild); + } + + var arrayCoords; + if (currentProjectionUnits === "DMS") { + arrayCoords = this._createDMSCoordinateElement("Lat", editCoordinates); + } else { + arrayCoords = this._createCoordinateElement("Lat", editCoordinates); + } + for (var i = 0; i < arrayCoords.length; i++) { + latElt.appendChild(arrayCoords[i]); + } + + // Suppression de tous les enfants de GPmousePositionLonCoordinate + var lonElt = document.getElementById(this._addUID("GPmousePositionLonCoordinate")); + while (lonElt.firstChild) { + lonElt.removeChild(lonElt.firstChild); + } + + var arrayCoords1; + if (currentProjectionUnits === "DMS") { + arrayCoords1 = this._createDMSCoordinateElement("Lon", editCoordinates); + } else { + arrayCoords1 = this._createCoordinateElement("Lon", editCoordinates); + } + for (var j = 0; j < arrayCoords1.length; j++) { + lonElt.appendChild(arrayCoords1[j]); + } + + // FIXME on simule un deplacement ? + // this.onMapMove(); + }, + + /** + * Set/unset editing mode + * + * @method _setEditMode + * @param {Boolean} editing - active edit coordinates mode + */ + _setEditMode : function (editing) { + var locateElt = document.getElementById(this._addUID("GPmousePositionLocate")); + locateElt.title = editing ? "Aller à la position ..." : "Cliquer pour saisir des coordonnées"; + + var closeEditElt = document.getElementById(this._addUID("GPmousePositionCloseEdit")); + closeEditElt.style.display = editing ? "inline-block" : "none"; + + var selector = "div[id^=" + this._addUID("GPmousePositionCoordinate") + "]"; + var inputs = document.querySelectorAll(selector + " input"); + for (var i = 0; i < inputs.length; i++) { + inputs[i].readOnly = !editing; + if (editing) { + inputs[i].value = ""; + inputs[i].classList.remove("error"); + } + } + var selects = document.querySelectorAll(selector + " select"); + for (var j = 0; j < selects.length; j++) { + selects[j].disabled = !editing; + } + }, + + /** + * + * @param {DOMElement} input - input element + * @param {Boolean} isFloat - check for float value + * + * @returns {Boolean} true if input value is within bounds + */ + _checkDMSElement : function (input, isFloat) { + var b = isFloat !== undefined; + + var value = input.value; + if (b) { + value = value.replace(",", "."); + } + if (isNaN(value)) { + return false; + } + + var v = parseFloat(value); + if (!b && (v | 0) !== v) { // is it an integer + return false; + } + + var min = Number(input.dataset.min); + var max = Number(input.dataset.max); + return (v >= min && v <= max); + }, + + /** + * @param {String} coordType - "Lon" or "Lat" + * @param {DOMElement} input - input element + * + * @returns {Boolean} true if input value is within bounds + */ + _checkDMSDegrees : function (coordType, input) { + if (isNaN(input.value)) { + return false; + } + + var v = parseFloat(input.value); + if ((v | 0) !== v) { // is it an integer + return false; + } + + var min = Number(input.dataset.min); + var max = Number(input.dataset.max); + if (v < min || v > max) { + return false; + } + + var inputMinutes = document.getElementById(this._addUID("GPmousePosition" + coordType + "Minutes")); + var inputSeconds = document.getElementById(this._addUID("GPmousePosition" + coordType + "Seconds")); + + if (v >= max) { + inputMinutes.dataset.max = 0; + inputSeconds.dataset.max = 0; + } else { + inputMinutes.dataset.max = 59; + inputSeconds.dataset.max = 59.9999; + } + + return true; + }, + + // ################################################################### // + // ####################### handlers Event ############################ // + // ################################################################### // + + /** + * Function displaying coordinates from cursor position (desktop) + * or map center (tactile) + * @param {Object} coordinate - coordinates + */ + GPdisplayCoords : function (coordinate) { + // Compute coords in case of cursor position (desktop) + if (coordinate && coordinate != null) { + var labelLon = document.getElementById(this._addUID("GPmousePositionLonLabel")); + var labelLat = document.getElementById(this._addUID("GPmousePositionLatLabel")); + + if (coordinate.x || coordinate.y) { + labelLat.innerHTML = "X : "; + labelLon.innerHTML = "Y : "; + } else if (coordinate.e || coordinate.n) { + labelLat.innerHTML = "E : "; + labelLon.innerHTML = "N : "; + } else { + labelLat.innerHTML = "Latitude : "; + labelLon.innerHTML = "Longitude : "; + } + + if (typeof coordinate.lat === "object" && typeof coordinate.lng === "object") { + var parts = { + lng : "Lon", + lat : "Lat" + }; + var units = ["Degrees", "Minutes", "Seconds"]; + for (var p in parts) { + for (var u = 0; u < units.length; ++u) { + var selector = "GPmousePosition" + parts[p] + units[u]; + var elt = document.getElementById(this._addUID(selector)); + var key = units[u].charAt(0).toLowerCase(); + elt.value = coordinate[p][key]; + } + } + // directions + document.getElementById(this._addUID("GPmousePositionLonDirection")).value = coordinate.lng.direction; + document.getElementById(this._addUID("GPmousePositionLatDirection")).value = coordinate.lat.direction; + } else { + var elLat = document.getElementById(this._addUID("GPmousePositionLat")); + var elLon = document.getElementById(this._addUID("GPmousePositionLon")); + + elLat.value = coordinate.x || coordinate.lat || coordinate.e || "0"; + elLon.value = coordinate.y || coordinate.lng || coordinate.lon || coordinate.n || "0"; + + // les unites + var unit = (coordinate.unit === undefined) ? "" : coordinate.unit; + var elements = document.getElementsByClassName("GPmousePositionUnits"); + for (var n = 0; n < elements.length; ++n) { + elements[n].innerHTML = unit; + } + } + } + }, + + /** + * Function displaying altitude from cursor position (desktop) + * or map center (tactile) + * @param {Object} coordinate - coordinates + * @param {Number} altitudeTimeoutDelay - when the mouse stop moving, delay before the altitude request is launched + * @param {Number} noDataValue - the no data value + * @param {Number} noDataValueTolerance - the no data value tolerance + */ + GPdisplayElevation : function (coordinate, altitudeTimeoutDelay, noDataValue, noDataValueTolerance) { + // contexte d'execution + var self = this; + + // Latency for altitude request + var altitudeTimeout; + if (!altitudeTimeoutDelay) { + altitudeTimeoutDelay = 500; + } + + clearTimeout(altitudeTimeout); + document.getElementById(this._addUID("GPmousePositionAlt")).innerHTML = "..."; + + if (noDataValue == null) { + noDataValue = -99999; + } + if (noDataValueTolerance == null) { + noDataValueTolerance = 99980; + } + var maxThreshold = noDataValue + noDataValueTolerance; + var minThreshold = noDataValue - noDataValueTolerance; + + // Compute coords in case of cursor position (desktop) + if (coordinate && coordinate != null) { + // If no altitude panel, don't call altitude request + if (document.getElementById(this._addUID("GPmousePositionAltitude"))) { + altitudeTimeout = setTimeout(function () { + self.onRequestAltitude(coordinate, function (z) { + if (minThreshold < z && z < maxThreshold) { + self.GPresetElevation(); + } else { + document.getElementById(self._addUID("GPmousePositionAlt")).innerHTML = z; + } + }); + }, altitudeTimeoutDelay); + } + } + }, + + /** + * Function reseting altitude value + */ + GPresetElevation : function () { + if (document.getElementById(this._addUID("GPmousePositionAltitude"))) { + document.getElementById(this._addUID("GPmousePositionAlt")).innerHTML = "---"; + } + } +}; + +export default MousePositionDOM; diff --git a/src/Common-review/Controls/ProfileElevationPathDOM.js b/src/Common-review/Controls/ProfileElevationPathDOM.js new file mode 100644 index 000000000..910c408f9 --- /dev/null +++ b/src/Common-review/Controls/ProfileElevationPathDOM.js @@ -0,0 +1,524 @@ +/* globals AmCharts, d3 */ +var ProfileElevationPathDOM = { + + /** + * Display Profile function used by default : no additonal framework needed. + * @param {Object} data - elevations values for profile + * @param {HTMLElement} container - html container where to display profile + * @param {Object} context - this control object + * @param {Object} className - calling class (ie ElevationPath) + * @returns {DOMElement} profil container + */ + displayProfileByDefault : function (data, container, context, className) { + var self = context; + + // on nettoie toujours... + if (container) { + while (container.firstChild) { + container.removeChild(container.firstChild); + } + } + + if (!data) { + return; + } + + var _displayProfileOptions = self.options.displayProfileOptions; + + var _points = data.points; + + var sortedElev = JSON.parse(JSON.stringify(_points)); + sortedElev.sort(function (e1, e2) { + return e1.z - e2.z; + }); + + var minZ = sortedElev[0].z; + var maxZ = sortedElev[sortedElev.length - 1].z; + var diff = maxZ - minZ; + var dist = data.distance; + var unit = data.unit; + // var distMin = 0; + var barwidth = 100 / _points.length; + + var div = document.createElement("div"); + div.id = "profileElevationByDefault"; + container.appendChild(div); + + var divBox = document.createElement("div"); + divBox.className = "profile-box"; + + var divZ = document.createElement("div"); + divZ.className = "profile-z-vertical"; + var ulZ = document.createElement("ul"); + var liZmin = document.createElement("li"); + liZmin.setAttribute("class", "profile-min-z"); + liZmin.innerHTML = minZ + " m"; + var liZmax = document.createElement("li"); + liZmax.setAttribute("class", "profile-max-z"); + liZmax.innerHTML = maxZ + " m"; + + // var divUnit = document.createElement("div"); + // divUnit.className = "profile-unit"; + // divUnit.innerHTML = "m"; + + ulZ.appendChild(liZmax); + ulZ.appendChild(liZmin); + divZ.appendChild(ulZ); + // divZ.appendChild(divUnit); + divBox.appendChild(divZ); + + var divData = document.createElement("div"); + divData.className = "profile-content"; + divData.addEventListener("mouseover", function (e) { + var _lon = parseFloat(e.target.dataset["lon"]); + var _lat = parseFloat(e.target.dataset["lat"]); + + if (_lon && _lat) { + className.__createProfileMarker(self, { + lat : _lat, + lon : _lon + }); + } + }); + divData.addEventListener("mousemove", function (e) { + var _lon = parseFloat(e.target.dataset["lon"]); + var _lat = parseFloat(e.target.dataset["lat"]); + + if (_lon && _lat) { + className.__updateProfileMarker(self, { + lat : _lat, + lon : _lon + }); + } + }); + divData.addEventListener("mouseout", function () { + className.__removeProfileMarker(self); + }); + + var ulData = document.createElement("ul"); + ulData.id = "profile-data"; + ulData.className = "profile-z-axis profile-x-axis"; + divData.appendChild(ulData); + + for (var i = 0; i < _points.length; i++) { + var d = _points[i]; + var li = document.createElement("li"); + li.setAttribute("data-z", d.z); + li.setAttribute("data-lon", d.lon); + li.setAttribute("data-lat", d.lat); + li.setAttribute("data-dist", d.dist); + + var pct = Math.floor((d.z - minZ) * 100 / diff); + li.setAttribute("class", "percent v" + pct); + li.title = "Altitude : " + d.z + "m"; + if (_displayProfileOptions.currentSlope) { + li.title += " - Pente : " + d.slope + "%"; + } + li.title += " (Lat : " + d.lat + " / Lon : " + d.lon + ")"; + + li.setAttribute("style", "width: " + barwidth + "%"); + ulData.appendChild(li); + } + + divBox.appendChild(divData); + div.appendChild(divBox); + + var divX = document.createElement("div"); + divX.className = "profile-x-horizontal"; + var ulX = document.createElement("ul"); + var liXmin = document.createElement("li"); + liXmin.setAttribute("class", "profile-min-x"); + liXmin.innerHTML = ""; + var liXmax = document.createElement("li"); + liXmax.setAttribute("class", "profile-max-x"); + liXmax.innerHTML = dist + " " + unit; + ulX.appendChild(liXmin); + ulX.appendChild(liXmax); + divX.appendChild(ulX); + div.appendChild(divX); + + return container; + }, + + /** + * Display Profile without graphical rendering (raw service response) + * @param {Object} data - elevations values for profile + * @param {HTMLElement} container - html container where to display profile + * @param {Object} context - this control object + * @param {Object} className - calling class (ie ElevationPath) + * @returns {DOMElement} profil container + */ + displayProfileRaw : function (data, container, context, className) { + // on nettoie toujours... + if (container) { + while (container.firstChild) { + container.removeChild(container.firstChild); + } + } + + var _points = data.points; + + var div = document.createElement("textarea"); + div.id = "profilElevationResults"; + div.rows = 10; + div.cols = 50; + div.style.width = "100%"; + div.innerHTML = JSON.stringify(_points, undefined, 4); + div.addEventListener("mouseover", function (e) { + className.__customRawProfileMouseOverEvent(context, e); + }); + + // TODO + // for (var i = 0; i < _points.length; i++) { + // var point = _points[i]; + // var divC = document.createElement("code"); + // divC.id = "point_" + i; + // divC.innerHTML = JSON.stringify(point, undefined, 4); + // div.appendChild(divC); + // divC.addEventListener("mouseover", function (e) { + // className.__customRawProfileMouseOverEvent(context, e); + // }); + // } + + container.appendChild(div); + + return container; + }, + + /** + * Display Profile using D3 javascript framework. This method needs D3 libraries to be loaded. + * @param {Object} data - elevations values for profile + * @param {HTMLElement} container - html container where to display profile + * @param {Object} context - this control object + * @param {Object} className - calling class (ie ElevationPath) + * @returns {DOMElement} profil container + */ + displayProfileLibD3 : function (data, container, context, className) { + var self = context; + + // on nettoie toujours... + if (container) { + while (container.firstChild) { + container.removeChild(container.firstChild); + } + } + + var _points = data.points; + + var _displayProfileOptions = self.options.displayProfileOptions; + + var margin = { + top : 20, + right : 20, + bottom : 30, + left : 40 + }; + + var width = container.clientWidth - margin.left - margin.right; + var height = container.clientHeight - margin.top - margin.bottom; + + var x = d3.scale.linear() + .range([0, width]); + + var y = d3.scale.linear() + .range([height, 0]); + + var xAxis = d3.svg.axis() + .scale(x) + .orient("bottom") + .ticks(5); + + var yAxis = d3.svg.axis() + .scale(y) + .orient("left") + .ticks(5); + + var line = d3.svg.line() + .interpolate("basis") + .x(function (d) { + return x(d.dist); + }) + .y(function (d) { + return y(d.z); + }); + + var area = d3.svg.area() + .interpolate("basis") + .x(function (d) { + return x(d.dist); + }) + .y0(height) + .y1(function (d) { + return y(d.z); + }); + + var svg = d3.select(container) + .append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + + var xDomain = d3.extent(_points, function (d) { + return d.dist; + }); + x.domain(xDomain); + + var yDomain = [ + 0, + d3.max(_points, function (d) { + return d.z; + }) + ]; + y.domain(yDomain); + + svg.append("path") + .datum(_points) + .attr("class", "area-d3") + .attr("d", area); + + svg.append("g") + .attr("class", "x axis-d3") + .attr("transform", "translate(0," + height + ")") + .call(xAxis) + .append("text") + .attr("y", -15) + .attr("dy", ".71em") + .attr("x", width) + .text("Distance (" + data.unit + ")"); + + svg.append("g") + .attr("class", "y axis-d3") + .call(yAxis) + .append("text") + .attr("transform", "rotate(-90)") + .attr("y", 6) + .attr("dy", ".71em") + .text("Altitude (m)"); + + svg.append("g") + .attr("class", "grid-d3 vertical") + .attr("transform", "translate(0," + height + ")") + .call(xAxis + .orient("bottom") + .tickSize(-height, 0, 0) + .tickFormat("") + ); + + svg.append("g") + .attr("class", "grid-d3 horizontal") + .call(yAxis + .orient("left") + .tickSize(-width, 0, 0) + .tickFormat("") + ); + + svg.append("path") + .datum(_points) + .attr("class", "line-d3") + .attr("d", line); + + svg.selectAll("circle") + .data(_points) + .enter() + .append("circle") + .attr("cx", function (d) { + return x(d.dist); + }) + .attr("cy", function (d) { + return y(d.z); + }) + .attr("r", 0) + .attr("class", "circle-d3"); + + var focus = svg.append("g").style("display", "none"); + + focus.append("line") + .attr("id", "focusLineX") + .attr("class", "focusLine-d3"); + focus.append("line") + .attr("id", "focusLineY") + .attr("class", "focusLine-d3"); + focus.append("circle") + .attr("id", "focusCircle") + .attr("r", 4) + .attr("class", "circle-d3 focusCircle-d3"); + + var div = d3.select(container).append("div") + .attr("class", "tooltip-d3") + .style("opacity", 0); + + var bisectDist = d3.bisector(function (d) { + return d.dist; + }).left; + + svg.append("rect") + .attr("class", "overlay-d3") + .attr("width", width) + .attr("height", height) + .on("mouseover", function () { + focus.style("display", null); + className.__createProfileMarker(self, _points[0]); + }) + .on("mouseout", function () { + focus.style("display", "none"); + className.__removeProfileMarker(self); + + // tooltips + div.transition() + .duration(500) + .style("opacity", 0); + }) + .on("mousemove", function () { + var m = d3.mouse(this); + var distance = x.invert(m[0]); + var i = bisectDist(_points, distance); + + var d0 = _points[i - 1]; + var d1 = _points[i]; + var d = distance - d0[0] > d1[0] - distance ? d1 : d0; + + var xc = x(d.dist); + var yc = y(d.z); + + focus.select("#focusCircle") + .attr("cx", xc) + .attr("cy", yc); + focus.select("#focusLineX") + .attr("x1", xc).attr("y1", y(yDomain[0])) + .attr("x2", xc).attr("y2", y(yDomain[1])); + focus.select("#focusLineY") + .attr("x1", x(xDomain[0])).attr("y1", yc) + .attr("x2", x(xDomain[1])).attr("y2", yc); + + className.__updateProfileMarker(self, d); + + // tooltips + div.transition() + .duration(200) + .style("opacity", 0.9); + + var _message = ""; + _message += " Altitude : " + d.z + " m"; + if (_displayProfileOptions.currentSlope) { + _message += "
Pente : " + d.slope + " %"; + } + _message += "
(Lat : " + d.lat + "/ Lon : " + d.lon + ")"; + + div.html(_message) + .style("left", (d3.event.pageX) + "px") + .style("top", (d3.event.pageY - 28) + "px"); + }); + + // return d3.selectAll("rect.overlay")[0][0]; + return svg; + }, + + /** + * Display Profile using Amcharts framework. This method needs AmCharts libraries to be loaded. + * @param {Object} data - elevations values for profile + * @param {HTMLElement} container - html container where to display profile + * @param {Object} context - this control object + * @param {Object} className - calling class (ie ElevationPath) + * @returns {DOMElement} profil container + */ + displayProfileLibAmCharts : function (data, container, context, className) { + var self = context; + + var _points = data.points; + + var ballonText = "[[title]] : [[value]]m
"; + var currentSlope = self.options.displayProfileOptions.currentSlope; + if (currentSlope) { + ballonText += "Pente : [[slope]] %
"; + } + ballonText += "(Lat: [[lat]] / Lon:[[lon]])"; + + AmCharts.addInitHandler(function () {}); + + var settings = { + type : "serial", + pathToImages : "http://cdn.amcharts.com/lib/3/images/", + categoryField : "dist", + autoMarginOffset : 0, + marginRight : 10, + marginTop : 10, + startDuration : 0, + color : "#5E5E5E", + fontSize : 8, + theme : "light", + thousandsSeparator : "", + numberFormatter : { + precision : -1, + decimalSeparator : ",", + thousandsSeparato : " " + }, + categoryAxis : { + color : "#5E5E5E", + gridPosition : "start", + minHorizontalGap : 40, + tickPosition : "start", + title : "Distance (" + data.unit + ")", + titleColor : "#5E5E5E", + labelOffset : 0, + startOnAxis : true + }, + chartCursor : { + animationDuration : 0, + bulletsEnabled : true, + bulletSize : 10, + categoryBalloonEnabled : false, + cursorColor : "#F90", + graphBulletAlpha : 1, + graphBulletSize : 1, + zoomable : false + }, + trendLines : [], + graphs : [{ + balloonColor : "#CCCCCC", + balloonText : ballonText, + bullet : "round", + bulletAlpha : 0, + bulletBorderColor : "#FFF", + bulletBorderThickness : 2, + bulletColor : "#F90", + bulletSize : 6, + hidden : false, + id : "AmGraph-1", + fillAlphas : 0.4, + fillColors : "#C77A04", + lineAlpha : 1, + lineColor : "#C77A04", + lineThickness : 1, + title : "Altitude", + valueField : "z" + }], + guides : [], + valueAxes : [{ + id : "ValueAxis-1", + minVerticalGap : 20, + title : "Altitude (m)" + }], + balloon : { + borderColor : "#CCCCCC", + borderThickness : 1, + fillColor : "#FFFFFF", + showBullet : true + }, + titles : [], + allLabels : [], + dataProvider : _points + }; + + var _containerProfile = AmCharts.makeChart(container, settings); + + _containerProfile.addListener("changed", function (e) { + var obj = e.chart.dataProvider[e.index]; + className.__updateProfileMarker(self, obj); + }); + + return _containerProfile; + } +}; + +export default ProfileElevationPathDOM; diff --git a/src/Common-review/Controls/ReverseGeocodingDOM.js b/src/Common-review/Controls/ReverseGeocodingDOM.js new file mode 100644 index 000000000..e2e59e29b --- /dev/null +++ b/src/Common-review/Controls/ReverseGeocodingDOM.js @@ -0,0 +1,463 @@ +var ReverseGeocodingDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPreverseGeocoding"); + container.className = "GPwidget"; + return container; + }, + + // ################################################################### // + // ################### Methods of main container ##################### // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing + * + * @returns {DOMElement} DOM element + */ + _createShowReverseGeocodingElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowReverseGeocoding"); + input.type = "checkbox"; + return input; + }, + + /** + * Show ReverseGeocoding + * + * @returns {DOMElement} DOM element + */ + _createShowReverseGeocodingPictoElement : function () { + // contexte d'execution + var self = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowReverseGeocodingPicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowReverseGeocoding"); + label.title = "Ouvrir la recherche inverse"; + + // Close all results and panels when minimizing the widget + if (label.addEventListener) { + label.addEventListener("click", function () { + self.onShowReverseGeocodingClick(); + }); + } else if (label.attachEvent) { + label.attachEvent("onclick", function () { + self.onShowReverseGeocodingClick(); + }); + } + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowReverseGeocodingOpen"); + spanOpen.className = "GPshowAdvancedToolOpen"; + label.appendChild(spanOpen); + + return label; + }, + + /** + * Create Waiting Panel + * + * @returns {DOMElement} DOM element + */ + _createReverseGeocodingWaitingElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPreverseGeocodingCalcWaitingContainer"); + div.className = "GPreverseGeocodingCalcWaitingContainerHidden"; + + var p = document.createElement("p"); + p.className = "GPreverseGeocodingCalcWaiting"; + p.innerHTML = "Recherche en cours..."; + + div.appendChild(p); + + return div; + }, + + /** + * Reverse geocoding results panel element. + * + * @returns {DOMElement} DOM element + */ + _createReverseGeocodingResultsPanelElement : function () { + var resultsPanelDiv = document.createElement("div"); + resultsPanelDiv.id = this._addUID("GPreverseGeocodingResultsPanel"); + resultsPanelDiv.className = "GPpanel GPreverseGeocodingComponentHidden"; + return resultsPanelDiv; + }, + + /** + * Reverse geocoding results list. + * + * @returns {DOMElement} DOM element + */ + _createReverseGeocodingResultsListElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPreverseGeocodingResultsList"); + // Results are dynamically filled in Javascript by reverse geocoding service + return container; + }, + + /** + * Add Result + * (results dynamically generate !) + * + * @param {String} locationDescription - reverse geocoded location results + * @param {Number} id - ID + */ + _createReverseGeocodingResultElement : function (locationDescription, id) { + // contexte + var context = this; + + var container = document.getElementById(this._addUID("GPreverseGeocodingResultsList")); + + var div = document.createElement("div"); + div.id = this._addUID("ReverseGeocodedLocation_" + id); + div.className = "GPautoCompleteProposal"; + div.innerHTML = locationDescription; + div.title = locationDescription; + + if (div.addEventListener) { + div.addEventListener("mouseover", function (e) { + context.onReverseGeocodingResultMouseOver(e); + }); + div.addEventListener("mouseout", function (e) { + context.onReverseGeocodingResultMouseOut(e); + }); + div.addEventListener("click", function (e) { + if (typeof context.onReverseGeocodingResultClick === "function") { + context.onReverseGeocodingResultClick(e); + } + }); + } else if (div.attachEvent) { + div.attachEvent("onmouseover", function (e) { + context.onReverseGeocodingResultMouseOver(e); + }); + div.attachEvent("onmouseout", function (e) { + context.onReverseGeocodingResultMouseOut(e); + }); + div.attachEvent("onclick", function (e) { + if (typeof context.onReverseGeocodingResultClick === "function") { + context.onReverseGeocodingResultClick(e); + } + }); + } + + container.appendChild(div); + }, + + // ################################################################### // + // ######################### Inputs panel ############################ // + // ################################################################### // + + /** + * Create Container Panel + * + * @returns {DOMElement} DOM element + */ + _createReverseGeocodingPanelElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPreverseGeocodingPanel"); + div.className = "GPpanel"; + + return div; + }, + + /** + * Create Header Panel + * + * @returns {DOMElement} DOM element + */ + _createReverseGeocodingPanelHeaderElement : function () { + var container = document.createElement("div"); + container.className = "GPpanelHeader"; + // info: on sépare les appels pour la création du picto de retour, + // du titre et de la croix de fermeture pour les récupérer dans le composant + return container; + }, + + /** + * Create return picto in panel header + * + * @returns {DOMElement} DOM element + */ + _createReverseGeocodingPanelReturnPictoElement : function () { + // contexte + var self = this; + + var divNew = document.createElement("div"); + divNew.id = this._addUID("GPreverseGeocodingReturnPicto"); + divNew.title = "Nouvelle recherche"; + divNew.className = "GPreverseGeocodingReturnPictoHidden"; + if (divNew.addEventListener) { + divNew.addEventListener("click", function (e) { + document.getElementById(self._addUID("GPreverseGeocodingResultsPanel")).className = "GProuteComponentHidden"; + document.getElementById(self._addUID("GPreverseGeocodingForm")).className = ""; + document.getElementById(self._addUID("GPreverseGeocodingHeaderTitle")).innerHTML = "Recherche inverse"; + document.getElementById(self._addUID("GPreverseGeocodingReturnPicto")).className = "GPreverseGeocodingReturnPictoHidden"; + self.onGPreverseGeocodingReturnPictoClick(e); + }); + } else if (divNew.attachEvent) { + divNew.attachEvent("onclick", function (e) { + document.getElementById(self._addUID("GPreverseGeocodingResultsPanel")).className = "GProuteComponentHidden"; + document.getElementById(self._addUID("GPreverseGeocodingForm")).className = ""; + document.getElementById(self._addUID("GPreverseGeocodingHeaderTitle")).innerHTML = "Recherche inverse"; + document.getElementById(self._addUID("GPreverseGeocodingReturnPicto")).className = "GPreverseGeocodingReturnPictoHidden"; + self.onGPreverseGeocodingReturnPictoClick(e); + }); + } + return divNew; + }, + + /** + * Create Header Title Panel + * + * @returns {DOMElement} DOM element + */ + _createReverseGeocodingPanelTitleElement : function () { + var div = document.createElement("div"); + div.className = "GPpanelTitle"; + div.id = this._addUID("GPreverseGeocodingHeaderTitle"); + div.innerHTML = "Recherche inverse"; + return div; + }, + + /** + * Create Header close div + * + * @returns {DOMElement} DOM element + */ + _createReverseGeocodingPanelCloseElement : function () { + // contexte + var self = this; + + var divClose = document.createElement("div"); + divClose.id = this._addUID("GPreverseGeocodingPanelClose"); + divClose.className = "GPpanelClose"; + divClose.title = "Fermer le panneau"; + + // Link panel close / visibility checkbox + if (divClose.addEventListener) { + divClose.addEventListener("click", function () { + document.getElementById(self._addUID("GPshowReverseGeocodingPicto")).click(); + }, false); + } else if (divClose.attachEvent) { + divClose.attachEvent("onclick", function () { + document.getElementById(self._addUID("GPshowReverseGeocodingPicto")).click(); + }); + } + + return divClose; + }, + + /** + * Create Form + * see event ! + * + * @returns {DOMElement} DOM element + */ + _createReverseGeocodingPanelFormElement : function () { + // contexte d'execution + var self = this; + + var form = document.createElement("form"); + form.id = this._addUID("GPreverseGeocodingForm"); + + if (form.addEventListener) { + form.addEventListener("submit", function (e) { + e.preventDefault(); + self.onReverseGeocodingSubmit(); + }); + } else if (form.attachEvent) { + form.attachEvent("onsubmit", function (e) { + e.preventDefault(); + self.onReverseGeocodingSubmit(); + }); + } + + return form; + }, + + // ################################################################### // + // ####################### Choice mode into form ##################### // + // ################################################################### // + + /** + * Create Container to Mode choice geocoding type + * + * @param {Array} resources - geocoding resources to be displayed (and used) + * @returns {DOMElement} DOM element + */ + _createReverseGeocodingFormModeChoiceGeocodingTypeElement : function (resources) { + // contexte d'execution + var context = this; + + var div = document.createElement("div"); + div.className = "GPflexInput"; + + var label = document.createElement("label"); + label.className = "GPreverseGeocodingCodeLabel"; + label.innerHTML = "Recherche par"; + label.title = "Recherche par"; + div.appendChild(label); + + var select = document.createElement("select"); + select.className = "GPreverseGeocodingCode"; + // gestionnaire d'evenement : on stocke la valeur du type de geocodage, + // utilisé dans la requête de géocodage inverse + if (select.addEventListener) { + select.addEventListener("change", function (e) { + context.onReverseGeocodingTypeChange(e); + }); + } else if (select.attachEvent) { + select.attachEvent("onchange", function (e) { + context.onReverseGeocodingTypeChange(e); + }); + } + + // on prend soit les valeurs passées par l'utilisateur, soit des valeurs par défaut + if (!resources || !Array.isArray(resources)) { + resources = ["StreetAddress", "PositionOfInterest", "CadastralParcel"]; + } + for (var i = 0; i < resources.length; i++) { + switch (resources[i]) { + case "PositionOfInterest": + var POIOption = document.createElement("option"); + POIOption.value = "PositionOfInterest"; + POIOption.text = "Lieux/toponymes"; + select.appendChild(POIOption); + break; + case "StreetAddress": + var SAOption = document.createElement("option"); + SAOption.value = "StreetAddress"; + SAOption.text = "Adresses"; + select.appendChild(SAOption); + break; + case "CadastralParcel": + var CPOption = document.createElement("option"); + CPOption.value = "CadastralParcel"; + CPOption.text = "Parcelles cadastrales"; + select.appendChild(CPOption); + break; + case "Administratif": + var adminOption = document.createElement("option"); + adminOption.value = "Administratif"; + adminOption.text = "Unités administratives"; + select.appendChild(adminOption); + break; + default: + break; + } + } + + div.appendChild(select); + + return div; + }, + + /** + * Create Container to Mode choice geocoding delimitation + * + * @param {Array} delimitations - geocoding delimitations to be displayed (and used) + * @returns {DOMElement} DOM element + */ + _createReverseGeocodingFormModeChoiceGeocodingDelimitationElement : function (delimitations) { + // contexte d'execution + var context = this; + + var div = document.createElement("div"); + div.className = "GPflexInput"; + + var label = document.createElement("label"); + label.className = "GPreverseGeocodingCodeLabel"; + label.innerHTML = "Délimitation"; + label.title = "Délimitation"; + div.appendChild(label); + + var select = document.createElement("select"); + select.className = "GPreverseGeocodingCode"; + // gestionnaire d'evenement : on stocke la valeur du type de délimitation, + // et on modifie l'événement de pointage sur la carte en fonction + if (select.addEventListener) { + select.addEventListener("change", function (e) { + context.onReverseGeocodingDelimitationChange(e); + }); + } else if (select.attachEvent) { + select.attachEvent("onchange", function (e) { + context.onReverseGeocodingDelimitationChange(e); + }); + } + + // on prend soit les valeurs passées par l'utilisateur, soit des valeurs par défaut + if (!delimitations || !Array.isArray(delimitations)) { + delimitations = ["Point", "Circle", "Extent"]; + } + for (var i = 0; i < delimitations.length; i++) { + switch (delimitations[i].toLowerCase()) { + case "point": + var pointOption = document.createElement("option"); + pointOption.value = "point"; + pointOption.text = "Pointer un lieu"; + select.appendChild(pointOption); + break; + case "circle": + var circleOption = document.createElement("option"); + circleOption.value = "circle"; + circleOption.text = "Dessiner un cercle"; + select.appendChild(circleOption); + break; + case "extent": + var extentOption = document.createElement("option"); + extentOption.value = "extent"; + extentOption.text = "Dessiner une emprise"; + select.appendChild(extentOption); + break; + default: + break; + } + } + + div.appendChild(select); + + return div; + }, + + // ################################################################### // + // ########################### Submit Form ########################### // + // ################################################################### // + + /** + * Create Submit Form Element + * + * @returns {DOMElement} DOM element + */ + _createReverseGeocodingSubmitFormElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPreverseGeocodingSubmit"); + input.className = "GPinputSubmit"; + input.type = "submit"; + input.value = "Rechercher"; + + return input; + } + +}; + +export default ReverseGeocodingDOM; diff --git a/src/Common-review/Controls/RouteDOM.js b/src/Common-review/Controls/RouteDOM.js new file mode 100644 index 000000000..bede85b74 --- /dev/null +++ b/src/Common-review/Controls/RouteDOM.js @@ -0,0 +1,1200 @@ +import ID from "../Utils/SelectorID"; +import Logger from "../../Common/Utils/LoggerByDefault"; + +var logger = Logger.getLogger("RouteDOM"); + +var RouteDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GProute"); + container.className = "GPwidget"; + return container; + }, + + // ################################################################### // + // ################# Methods to display Main Panel ################### // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing panel + * + * @returns {DOMElement} DOM element + */ + _createShowRouteElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowRoute"); + input.type = "checkbox"; + return input; + }, + + /** + * Show route control + * see event ! + * + * @returns {DOMElement} DOM element + */ + _createShowRoutePictoElement : function () { + // contexte d'execution + var context = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowRoutePicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowRoute"); + label.title = "Ouvrir le calcul d'itinéraire"; + + // gestionnaire d'evenement : + // on ouvre le menu de saisie du calcul d'itiniraire + // L'ouverture/Fermeture permet de faire le menage + // (reinitialisation) + if (label.addEventListener) { + label.addEventListener("click", function (e) { + context.onShowRoutePanelClick(e); + }); + } else if (label.attachEvent) { + label.attachEvent("onclick", function (e) { + context.onShowRoutePanelClick(e); + }); + } + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowRouteOpen"); + spanOpen.className = "GPshowAdvancedToolOpen"; + label.appendChild(spanOpen); + + return label; + }, + + // ################################################################### // + // ################## Methods to display Inputs Panel ################ // + // ################################################################### // + + /** + * Create Container Panel + * + * FIXME + * don't call this._createRoutePanelHeaderElement + * don't call this._createRoutePanelFormElement + * don't call this._createRoutePanelResultsElement + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GProutePanel"); + div.className = "GPpanel"; + + // div.appendChild(this._createRoutePanelHeaderElement()); + // div.appendChild(this._createRoutePanelFormElement()); + // div.appendChild(this._createRoutePanelResultsElement()); + + return div; + }, + + /** + * Create Header Panel + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelHeaderElement : function () { + // contexte d'execution + var self = this; + + var container = document.createElement("div"); + container.className = "GPpanelHeader"; + + var div = document.createElement("div"); + div.className = "GPpanelTitle"; + div.innerHTML = "Calcul d'itinéraire"; + container.appendChild(div); + + var divClose = document.createElement("div"); + divClose.id = this._addUID("GProutePanelClose"); + divClose.className = "GPpanelClose"; + divClose.title = "Masquer le panneau"; + + // Link panel close / visibility checkbox + if (divClose.addEventListener) { + divClose.addEventListener("click", function () { + document.getElementById(self._addUID("GPshowRoutePicto")).click(); + }, false); + } else if (divClose.attachEvent) { + divClose.attachEvent("onclick", function () { + document.getElementById(self._addUID("GPshowRoutePicto")).click(); + }); + } + container.appendChild(divClose); + + return container; + }, + + /** + * Create Form + * see evenement ! + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelFormElement : function () { + // contexte d'execution + var self = this; + + var form = document.createElement("form"); + form.id = this._addUID("GProuteForm"); + form.setAttribute("onkeypress", "return event.keyCode != 13;"); // FIXME hack pour desactiver l'execution via 'enter' au clavier ! + + form.addEventListener("submit", function (e) { + logger.log(e); + e.preventDefault(); + + // points + var points = document.getElementsByClassName(self._addUID("GPlocationPoint")); + + // Must have at least two origin points + var start = points[0].childNodes[0].id; + var end = points[points.length - 1].childNodes[0].id; + var startID = ID.index(start); + var endID = ID.index(end); + + if ((document.getElementById(self._addUID("GPlocationOrigin_" + startID)).value === "" && + document.getElementById(self._addUID("GPlocationOriginCoords_" + startID)).value === "") || + (document.getElementById(self._addUID("GPlocationOrigin_" + endID)).value === "" && + document.getElementById(self._addUID("GPlocationOriginCoords_" + endID)).value === "")) { + return false; + } + + // Send stages to results panel + var id; + document.getElementById(self._addUID("GProuteResultsStages")).innerHTML = ""; + for (var i = 0; i < points.length; i++) { + var tag = points[i].childNodes[0].id; + id = ID.index(tag); + if (document.getElementById(self._addUID("GPlocationPoint_" + id)).className === "GPflexInput GPlocationStageFlexInput") { + var resultStage = document.createElement("div"); + resultStage.className = "GProuteResultsStages"; + var resultStageLabel = document.createElement("div"); + resultStageLabel.className = "GProuteResultStageLabel"; + resultStageLabel.innerHTML = document.getElementById(self._addUID("GPlocationOriginLabel_" + id)).innerHTML + " :"; + resultStage.appendChild(resultStageLabel); + var resultStageValue = document.createElement("div"); + resultStageValue.className = "GProuteResultStageValue"; + var elementCoords = document.getElementById(self._addUID("GPlocationOriginCoords_" + id)); + var stageCoords = elementCoords.value; + var visible = (elementCoords.className === "GPlocationOriginVisible"); + if (stageCoords !== null && stageCoords !== "" && visible) { + resultStageValue.innerHTML = stageCoords; + } else { + resultStageValue.innerHTML = document.getElementById(self._addUID("GPlocationOrigin_" + id)).value; + } + resultStage.appendChild(resultStageValue); + if (resultStageValue.innerHTML !== "") { + document.getElementById(self._addUID("GProuteResultsStages")).appendChild(resultStage); + } + } + } + + // on peut récuperer les valeurs utiles pour les transmettre au service d'iti... + // - le mode de calcul + // - le mode de transport + // - les exclusions + // Les points sont déjà stockés dans l'application. + + // computation mode params + var modeComputation = null; + if (document.getElementById(self._addUID("GProuteComputationSelect"))) { + var select = document.getElementById(self._addUID("GProuteResultsComputationSelect")); + select.selectedIndex = document.getElementById(self._addUID("GProuteComputationSelect")).selectedIndex; + modeComputation = select.options[select.selectedIndex].value; + } + + // transport mode params + var modeTransport = null; + // voiture ? + if (document.getElementById(self._addUID("GProuteTransportCar"))) { + if (document.getElementById(self._addUID("GProuteTransportCar")).checked) { + modeTransport = document.getElementById(self._addUID("GProuteTransportCar")).value; + } + } + // pieton ? + if (document.getElementById(self._addUID("GProuteTransportPedestrian"))) { + if (document.getElementById(self._addUID("GProuteTransportPedestrian")).checked) { + modeTransport = document.getElementById(self._addUID("GProuteTransportPedestrian")).value; + } + } + + // exclusions params + var exclusions = []; + var exclusionsElement = document.getElementsByClassName("GProuteExclusionsOption"); + for (var j = 0; j < exclusionsElement.length; j++) { + id = exclusionsElement[j].htmlFor; + var el = document.getElementById(id); + if (!el.checked) { + exclusions.push(el.value); + } + } + + self.onRouteComputationSubmit({ + computation : modeComputation, + transport : modeTransport, + exclusions : exclusions + }); + + // FIXME mise à jour du controle dans le composant JS ! + // document.getElementById(self._addUID("GProuteForm")).className = "GProuteComponentHidden"; + // document.getElementById(self._addUID("GProuteResultsPanel")).className = ""; + + return false; + }); + + return form; + }, + + /** + * Create Results Panel + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelResultsElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GProuteResultsPanel"); + container.className = "GProuteComponentHidden"; + + container.appendChild(this._createRouteResultsStagesElement()); + container.appendChild(this._createRouteResultsElement()); + + var divBorderUp = document.createElement("div"); + divBorderUp.className = "GPfakeBorder GPfakeBorderLeft"; + container.appendChild(divBorderUp); + + container.appendChild(this._createRouteShowResultsDetailsElement()); + + var labelShow = document.createElement("label"); + labelShow.htmlFor = this._addUID("GProuteResultsShowDetails"); + labelShow.innerHTML = "Afficher le détail"; + container.appendChild(labelShow); + + var labelHide = document.createElement("label"); + labelHide.htmlFor = this._addUID("GProuteResultsShowDetails"); + labelHide.innerHTML = "Masquer le détail"; + container.appendChild(labelHide); + + var divBorderDown = document.createElement("div"); + divBorderDown.className = "GPfakeBorder"; + container.appendChild(divBorderDown); + + container.appendChild(this._createRouteResultsDetailsElement()); + + return container; + }, + + /** + * Create Waiting Panel + * + * @returns {DOMElement} DOM element + */ + _createRouteWaitingElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GProuteCalcWaitingContainer"); + div.className = "GProuteCalcWaitingContainerHidden"; + + var p = document.createElement("p"); + p.className = "GProuteCalcWaiting"; + p.innerHTML = "Calcul en cours..."; + + div.appendChild(p); + + return div; + }, + // ################################################################### // + // ############### Methods to the window results ##################### // + // ################################################################### // + + /** + * Create Results Stages + * (results dynamically generate !) + * + * @returns {DOMElement} DOM element + */ + _createRouteResultsStagesElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GProuteResultsStages"); + return div; + }, + + /** + * Create Show Results + * see event! + * + * @returns {DOMElement} DOM element + */ + _createRouteResultsElement : function () { + // contexte + var self = this; + + var container = document.createElement("div"); + container.id = this._addUID("GProuteResults"); + + // FIXME Route results are dynamically filled in Javascript by route service + var divValue = document.createElement("div"); + divValue.id = this._addUID("GProuteResultsValues"); + container.appendChild(divValue); + + var divMode = document.createElement("div"); + divMode.id = this._addUID("GProuteResultsMode"); + + var select = document.createElement("select"); + select.id = this._addUID("GProuteResultsComputationSelect"); + select.className = "GPinputSelect"; + // gestionnaire d'evenement : + // on stocke la valeur du mode de calcul, et on relance le calcul d'itiniraire + select.addEventListener("change", function (e) { + self.onRouteModeComputationChangeAndRun(e); + }); + + var computes = [{ + code : "fastest", + label : "Plus rapide" + }, { + code : "shortest", + label : "Plus court" + }]; + + for (var i = 0; i < computes.length; i++) { + var option = document.createElement("option"); + option.value = computes[i].code; + option.text = computes[i].label; + select.appendChild(option); + } + divMode.appendChild(select); + container.appendChild(divMode); + + var divNew = document.createElement("div"); + divNew.id = this._addUID("GProuteResultsNew"); + divNew.title = "Modifier le calcul"; + divNew.addEventListener("click", function (e) { + document.getElementById(self._addUID("GProuteResultsPanel")).className = "GProuteComponentHidden"; + document.getElementById(self._addUID("GProuteForm")).className = ""; + self.onShowRouteResultsNewClick(e); + }); + container.appendChild(divNew); + + return container; + }, + + /** + * Add Results Duration and Distance + * (results dynamically generate !) + * see event! + * @param {Number} distance - distance + * @param {Number} duration - duration + * @param {Function} fconvert - fconvert + * + * @returns {DOMElement} DOM element + */ + _addRouteResultsValuesElement : function (distance, duration, fconvert) { + var div = document.getElementById(this._addUID("GProuteResultsValues")); + + // clean ! + if (div.childElementCount) { + while (div.firstChild) { + div.removeChild(div.firstChild); + } + } + + var containerDistance = document.createElement("div"); + containerDistance.className = "GProuteResultsValue"; + + var labelDistance = document.createElement("label"); + labelDistance.className = "GProuteResultsValueLabel"; + labelDistance.innerHTML = "Distance :"; + containerDistance.appendChild(labelDistance); + + var distanceLabel = 0; + var isKm = parseInt(distance / 1000, 10); + + if (!isKm) { + distanceLabel = Math.round(distance) + " m"; + } else { + var distanceArrondi = Math.round(distance); + distanceArrondi = distanceArrondi / 1000; + distanceLabel = distanceArrondi + " km"; + } + + var divDistance = document.createElement("div"); + divDistance.id = this._addUID("GProuteResultsValueDist"); + divDistance.innerHTML = distanceLabel; + containerDistance.appendChild(divDistance); + + div.appendChild(containerDistance); + + var containerDuration = document.createElement("div"); + containerDuration.className = "GProuteResultsValue"; + + var labelDuration = document.createElement("label"); + labelDuration.className = "GProuteResultsValueLabel"; + labelDuration.innerHTML = "Durée :"; + containerDuration.appendChild(labelDuration); + + var divDuration = document.createElement("div"); + divDuration.id = this._addUID("GProuteResultsValueDist"); + divDuration.innerHTML = fconvert(duration); + containerDuration.appendChild(divDuration); + + div.appendChild(containerDuration); + + return div; + }, + + /** + * Create Show Results Details + * + * @returns {DOMElement} DOM element + */ + _createRouteShowResultsDetailsElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GProuteResultsShowDetails"); + input.type = "checkbox"; + return input; + }, + + /** + * Create Results Details + * + * @returns {DOMElement} DOM element + */ + _createRouteResultsDetailsElement : function () { + // + var div = document.createElement("div"); + div.id = this._addUID("GProuteResultsDetails"); + return div; + }, + + /** + * Add Results Details + * (results dynamically generate !) + * @param {Object[]} instructions - instructions + * @param {Function} fconvert - fconvert + * + * @returns {DOMElement} DOM element + */ + _addRouteResultsDetailsElement : function (instructions, fconvert) { + // contexte + var context = this; + + var div = document.getElementById(this._addUID("GProuteResultsDetails")); + + // clean ! + if (div.childElementCount) { + while (div.firstChild) { + div.removeChild(div.firstChild); + } + } + + // calcul des valeurs cumulé ! + var distanceCumul = 0; + var durationCumul = 0; + + /* jshint -W083 */ + for (var i = 0; i < instructions.length; i++) { + var id = i + 1; + + var o = instructions[i]; + + var divNum = document.createElement("div"); + divNum.className = "GProuteResultsDetailsNumber"; + divNum.innerHTML = id + "."; + div.appendChild(divNum); + + durationCumul += parseFloat(o.duration); + distanceCumul += parseFloat(o.distance); + + var distance = 0; + var isCumulKm = parseInt(distanceCumul / 1000, 10); + if (!isCumulKm) { + distance = Math.round(distanceCumul) + " m"; + } else { + var distanceArrondi = Math.round(distanceCumul); + distanceArrondi = distanceArrondi / 1000; + distance = distanceArrondi + " km"; + } + + var divIns = document.createElement("div"); + divIns.className = "GProuteResultsDetailsInstruction"; + divIns.id = this._addUID("GProuteResultsDetailsInstruction_" + id); + divIns.title = "distance : " + distance + " / " + "temps : " + fconvert(durationCumul); + divIns.innerHTML = o.instruction; + + divIns.addEventListener("mouseover", function (e) { + context.onRouteResultsDetailsMouseOver(e); + }); + divIns.addEventListener("mouseout", function (e) { + context.onRouteResultsDetailsMouseOut(e); + }); + divIns.addEventListener("click", function (e) { + // mode mobile ! + if (typeof context.onRouteResultsDetailsClick === "function") { + context.onRouteResultsDetailsClick(e); + } + }); + div.appendChild(divIns); + } + + return div; + }, + + // ################################################################### // + // ################### Methods to the form points #################### // + // ################# OVERWRITTEN BY LOCATIONSELECTOR ! ################# // + + /** + * Create Point + * see event ! + * OVERWRITTEN BY LOCATIONSELECTOR ! + * (version initial without LOCATIONSELECTOR PLUGIN) + * @param {Integer} n - n + * @param {String} text - text + * @param {Boolean} visibility - visibility + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelFormPointElement : function (n, text, visibility) { + // contexte d'execution + var context = this; + + var div = document.createElement("div"); + div.id = "GProutePoint" + n; + div.className = (visibility) ? "GPflexInput GProuteStageFlexInput" : "GPflexInput GProuteStageFlexInputHidden"; + + var labelOrigin = document.createElement("label"); + labelOrigin.id = "GProuteOriginLabel" + n; + labelOrigin.htmlFor = "GProuteOrigin" + n; + labelOrigin.innerHTML = text; + labelOrigin.addEventListener("click", function () { + var i = this.id.charAt(this.id.length - 1); + document.getElementById("GProuteOriginCoords" + i).value = ""; + for (var j = 1; j < 8; j++) { + document.getElementById("GProutePoint" + j).style.display = "flex"; + } + document.getElementById("GProuteForm").className = ""; + document.getElementById("GProuteOriginPointer" + i).checked = false; + document.getElementById("GProuteOrigin" + i).className = "GProuteOriginVisible"; + document.getElementById("GProuteOriginCoords" + i).className = "GProuteOriginHidden"; + }); + div.appendChild(labelOrigin); + + var inputOrigin = document.createElement("input"); + inputOrigin.id = "GProuteOrigin" + n; + inputOrigin.className = "GProuteOriginVisible"; + inputOrigin.type = "text"; + inputOrigin.placeholder = "Saisir une adresse"; + inputOrigin.addEventListener("keyup", function (e) { + var charCode = e.which || e.keyCode; + if (charCode === 13 || charCode === 10) { + return; + } + var i = this.id.charAt(this.id.length - 1); + if (document.getElementById("GProuteOrigin" + i).value.length > 2) { + document.getElementById("GProuteAutoCompleteList" + i).style.display = "block"; + } else { + document.getElementById("GProuteAutoCompleteList" + i).style.display = "none"; + } + // gestionnaire d'evenement : + // on récupère la valeur de saisie pour une requête sur le service d'autocompletion. + // le resultat de la requête nous permet de recuperer les coordonnées du point... + context.onAutoCompleteSearchText(e); + }); + inputOrigin.addEventListener("blur", function () { + var i = this.id.charAt(this.id.length - 1); + document.getElementById("GProuteAutoCompleteList" + i).style.display = "none"; + }); + div.appendChild(inputOrigin); + + var inputOriginCoord = document.createElement("input"); + inputOriginCoord.id = "GProuteOriginCoords" + n; + inputOriginCoord.className = "GProuteOriginHidden"; + inputOriginCoord.type = "text"; + inputOriginCoord.disabled = true; + div.appendChild(inputOriginCoord); + + var inputOriginPointer = document.createElement("input"); + inputOriginPointer.id = "GProuteOriginPointer" + n; + inputOriginPointer.type = "checkbox"; + div.appendChild(inputOriginPointer); + + var labelOriginPointer = document.createElement("label"); + labelOriginPointer.id = "GProuteOriginPointerImg" + n; + labelOriginPointer.htmlFor = "GProuteOriginPointer" + n; + labelOriginPointer.className = "GProuteOriginPointerImg"; + labelOriginPointer.title = "Pointer un lieu sur la carte"; + labelOriginPointer.addEventListener("click", function (evt) { + evt.preventDefault(); + evt.stopPropagation(); + var i = this.id.charAt(this.id.length - 1); + var j; + for (j = 1; j < 8; j++) { + if (i !== j) { + document.getElementById("GProuteOriginPointer" + j).checked = false; + if (document.getElementById("GProuteOriginCoords" + j).value === "Pointer un lieu sur la carte") { + document.getElementById("GProuteOriginCoords" + j).value = ""; + document.getElementById("GProuteOrigin" + j).className = "GProuteOriginVisible"; + document.getElementById("GProuteOriginCoords" + j).className = "GProuteOriginHidden"; + } + } + } + if (document.getElementById("GProuteOriginPointer" + i).checked) { + document.getElementById("GProuteOriginCoords" + i).value = ""; + for (j = 1; j < 8; j++) { + document.getElementById("GProutePoint" + j).style.display = "flex"; + } + document.getElementById("GProuteForm").className = ""; + document.getElementById("GProuteOriginPointer" + i).checked = false; + document.getElementById("GProuteOrigin" + i).className = "GProuteOriginVisible"; + document.getElementById("GProuteOriginCoords" + i).className = "GProuteOriginHidden"; + } else { + document.getElementById("GProuteOriginCoords" + i).value = "Pointer un lieu sur la carte"; + for (j = 1; j < 8; j++) { + if (i === j) { + document.getElementById("GProutePoint" + j).style.display = "flex"; + } else { + document.getElementById("GProutePoint" + j).style.display = "none"; + } + } + document.getElementById("GProuteForm").className = "GProuteFormMini"; + document.getElementById("GProuteOriginPointer" + i).checked = true; + document.getElementById("GProuteOrigin" + i).className = "GProuteOriginHidden"; + document.getElementById("GProuteOriginCoords" + i).className = "GProuteOriginVisible"; + } + // gestionnaire d'evenement : + // on stocke la valeur du point, utilisée pour la requête sur le service de calcul d'itiniraire + context.onRouteMapPointClick(evt); + }); + div.appendChild(labelOriginPointer); + + return div; + }, + + /** + * Create Remove Point tag + * see event ! + * OVERWRITTEN BY LOCATIONSELECTOR ! + * (version initial without LOCATIONSELECTOR PLUGIN) + * @param {Integer} n - n + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelFormRemoveStageElement : function (n) { + // contexte d'execution + var context = this; + + var divRm = document.createElement("div"); + divRm.id = "GProuteStageRemove" + n; + divRm.className = "GProuteStageRemove"; + divRm.title = "Supprimer l'étape"; + if (n !== 1 && n !== 7) { + divRm.addEventListener("click", function (e) { + var i = this.id.charAt(this.id.length - 1); + document.getElementById("GProutePoint" + i).className = "GPflexInput GProuteStageFlexInputHidden"; + document.getElementById("GProuteOrigin" + i).value = ""; + document.getElementById("GProuteOrigin" + i).className = "GProuteOriginVisible"; + document.getElementById("GProuteOriginCoords" + i).value = ""; + document.getElementById("GProuteOriginCoords" + i).className = "GProuteOriginHidden"; + document.getElementById("GProuteStageAdd").style.display = ""; + // Moving up exclusions picto + // var exclusionsPictoTop = document.getElementById("GPshowRouteExclusionsPicto").style.top; + // document.getElementById("GPshowRouteExclusionsPicto").style.top = (parseInt(exclusionsPictoTop, 10) - 33).toString() + "px"; + // gestionnaire d'evenement : + // on supprime le point, utilisé pour la requête sur le service d'itiniraire + context.onRouteRemovePointClick(e); + }); + } + return divRm; + }, + + /** + * Create Add Point tag + * see event ! + * OVERWRITTEN BY LOCATIONSELECTOR ! + * (version initial without LOCATIONSELECTOR PLUGIN) + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelFormAddStageElement : function () { + // contexte d'execution + var context = this; + + var divAdd = document.createElement("div"); + divAdd.id = "GProuteStageAdd"; + divAdd.title = "Ajouter une étape"; + divAdd.addEventListener("click", function (e) { + var lastStage = 1; + var nbStages = 0; + for (var i = 2; i < 7; i++) { + if (document.getElementById("GProutePoint" + i).className === "GPflexInput GProuteStageFlexInputHidden") { + if (lastStage === 1) { + lastStage = i; + } + } else { + nbStages++; + } + } + if (lastStage < 7) { + document.getElementById("GProutePoint" + lastStage).className = "GPflexInput GProuteStageFlexInput"; + // Moving down exclusions picto + // var exclusionsPictoTop = document.getElementById("GPshowRouteExclusionsPicto").style.top; + // document.getElementById("GPshowRouteExclusionsPicto").style.top = (parseInt(exclusionsPictoTop, 10) + 33).toString() + "px"; + } + if (nbStages === 4) { + document.getElementById("GProuteStageAdd").style.display = "none"; + } + // gestionnaire d'evenement : + // on ajoute le point, utilisé pour la requête sur le service d'itiniraire + context.onRouteAddPointClick(e); + }); + + return divAdd; + }, + + /** + * Create Results autocompletion to the point + * see event! + * OVERWRITTEN BY LOCATIONSELECTOR ! + * (version initial without LOCATIONSELECTOR PLUGIN) + * @param {Integer} n - n + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelFormAutoCompleteListElement : function (n) { + // contexte d'execution + var context = this; + + var div = document.createElement("div"); + div.id = "GProuteAutoCompleteList" + n; + div.className = "GPadvancedAutoCompleteList"; + + if (div.addEventListener) { + div.addEventListener("click", function (e) { + context.onAutoCompletedResultsItemClick(e); + document.getElementById("GProuteAutoCompleteList" + n).style.display = "none"; + }, false); + } else if (div.attachEvent) { + div.attachEvent("onclick", function (e) { + context.onAutoCompletedResultsItemClick(e); + document.getElementById("GProuteAutoCompleteList" + n).style.display = "none"; + }); + } + + // Proposals are dynamically filled in Javascript by autocomplete service + //
...
+ + return div; + }, + + /** + * Autocompletion result to a point. + * Proposals are dynamically filled in Javascript by autocomplete service + * OVERWRITTEN BY LOCATIONSELECTOR ! + * (version initial without LOCATIONSELECTOR PLUGIN) + * + * + * @param {Object} location - suggested location results + * @param {Number} n - number of the point + * @param {Number} id - ID + */ + _createRouteAutoCompletedLocationElement : function (location, n, id) { + var container = document.getElementById("GProuteAutoCompleteList" + n); + + var div = document.createElement("div"); + div.id = "AutoCompletedLocation" + id; + div.className = "GPautoCompleteProposal"; + div.innerHTML = location.fullText; + + container.appendChild(div); + }, + + // ################################################################### // + // ############## Methods to the choice mode into form ############### // + // ################################################################### // + + /** + * Create Container to Mode choice transport + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelFormModeChoiceElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GProuteModeChoice"); + + // div.appendChild(this._createRoutePanelFormModeChoiceTransportElement()); + // div.appendChild(this._createRoutePanelFormModeChoiceComputeElement()); + + return div; + }, + + /** + * Create Mode choice transport + * see event ! + * FIXME event not useful + * @param {String[]} transports - transports + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelFormModeChoiceTransportElement : function (transports) { + // contexte d'execution + var context = this; + + var div = document.createElement("div"); + div.id = this._addUID("GProuteTransportChoice"); + + var span = document.createElement("span"); + span.className = "GProuteModeLabel"; + span.innerHTML = "Mode de transport"; + div.appendChild(span); + + /* jshint -W083 */ + for (var i = 0; i < transports.length; i++) { + var transport = transports[i]; + + if (transport === "Voiture") { + var inputCar = document.createElement("input"); + inputCar.id = this._addUID("GProuteTransportCar"); + inputCar.type = "radio"; + inputCar.name = "GProuteTransport"; + inputCar.value = "Voiture"; + if (i === 0) { + inputCar.checked = true; + } + // gestionnaire d'evenement : + // on stocke le mode de transport, + // utilisation pour la requête sur le service de calcul d'itiniraire + if (inputCar.addEventListener) { + inputCar.addEventListener("change", function (e) { + context.onRouteModeTransportChange(e); + }); + } else if (inputCar.attachEvent) { + inputCar.attachEvent("onchange", function (e) { + context.onRouteModeTransportChange(e); + }); + } + div.appendChild(inputCar); + + var labelCar = document.createElement("label"); + labelCar.className = "GProuteTransportImg"; + labelCar.htmlFor = this._addUID("GProuteTransportCar"); + labelCar.title = "Voiture"; + div.appendChild(labelCar); + } + + if (transport === "Pieton") { + var inputPedestrian = document.createElement("input"); + inputPedestrian.id = this._addUID("GProuteTransportPedestrian"); + inputPedestrian.type = "radio"; + inputPedestrian.name = "GProuteTransport"; + inputPedestrian.value = "Pieton"; + if (i === 0) { + inputPedestrian.checked = true; + } + // gestionnaire d'evenement : + // on stocke le mode de transport, + // utilisation pour la requête sur le service de calcul d'itiniraire + if (inputPedestrian.addEventListener) { + inputPedestrian.addEventListener("change", function (e) { + context.onRouteModeTransportChange(e); + }); + } else if (inputPedestrian.attachEvent) { + inputPedestrian.attachEvent("onchange", function (e) { + context.onRouteModeTransportChange(e); + }); + } + div.appendChild(inputPedestrian); + + var labelPedestrian = document.createElement("label"); + labelPedestrian.className = "GProuteTransportImg"; + labelPedestrian.htmlFor = this._addUID("GProuteTransportPedestrian"); + labelPedestrian.title = "Piéton"; + div.appendChild(labelPedestrian); + } + } + + return div; + }, + + /** + * Create Mode choice computation + * see event! + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelFormModeChoiceComputeElement : function () { + // contexte d'execution + var context = this; + + var div = document.createElement("div"); + div.id = this._addUID("GProuteComputationChoice"); + + var span = document.createElement("span"); + span.className = "GProuteModeLabel"; + span.innerHTML = "Mode de calcul"; + div.appendChild(span); + + var select = document.createElement("select"); + select.id = this._addUID("GProuteComputationSelect"); + select.className = "GPinputSelect"; + // gestionnaire d'evenement : + // on stocke la valeur du mode de calcul, + // utilisation pour la requête sur le service de calcul d'itiniraire + select.addEventListener("change", function (e) { + context.onRouteModeComputationChange(e); + }); + + var computes = [{ + code : "fastest", + label : "Plus rapide" + }, { + code : "shortest", + label : "Plus court" + }]; + + for (var i = 0; i < computes.length; i++) { + var option = document.createElement("option"); + option.value = computes[i].code; + option.text = computes[i].label; + select.appendChild(option); + } + div.appendChild(select); + + return div; + }, + + // ################################################################### // + // ################# Methods to the choice exclusions ################ // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing Exclusions Options + * + * @returns {DOMElement} DOM element + */ + _createShowRouteExclusionsElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowRouteExclusions"); + input.type = "checkbox"; + return input; + }, + + /** + * Label to Exclusions Options + * see event ! + * FIXME event not useful + * + * @returns {DOMElement} DOM element + */ + _createShowRouteExclusionsPictoElement : function () { + // contexte d'execution + var context = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowRouteExclusionsPicto"); + label.className = "GPshowMoreOptionsImage GPshowMoreOptions GPshowRouteExclusionsPicto"; + label.htmlFor = this._addUID("GPshowRouteExclusions"); + label.title = "Exclusions"; + // label.style.top = "185px"; + + // gestionnaire d'evenement : + // on ouvre le menu des options des exclusions + if (label.addEventListener) { + label.addEventListener("click", function (e) { + context.onShowRouteExclusionsClick(e); + }); + } else if (label.attachEvent) { + label.attachEvent("onclick", function (e) { + context.onShowRouteExclusionsClick(e); + }); + } + + return label; + }, + + /** + * Create Container to Exclusions + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelFormExclusionsElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GProuteExclusions"); + + var span = document.createElement("span"); + span.className = "GProuteExclusionsLabel"; + span.innerHTML = "Passages autorisés"; + div.appendChild(span); + + // div.appendChild(this._createRoutePanelFormExclusionOptionsElement()); + + return div; + }, + + /** + * Create Exclusions Options + * see event ! + * FIXME event not useful + * @param {Object[]} exclusions - exclusions + * + * @returns {DOMElement} DOM element + */ + _createRoutePanelFormExclusionOptionsElement : function (exclusions) { + // contexte d'execution + var context = this; + + var div = document.createElement("div"); + div.className = "GProuteExclusionsOptions"; + + /* jshint -W083 */ + for (var value in exclusions) { + if (exclusions.hasOwnProperty(value)) { + var status = exclusions[value]; + switch (value) { + case "toll": + var inputToll = document.createElement("input"); + inputToll.id = this._addUID("GProuteExclusionsToll"); + inputToll.type = "checkbox"; + inputToll.value = "Toll"; + inputToll.checked = !status; + // gestionnaire d'evenement : + // on stocke l'exclusion, + // utilisation pour la requête sur le service de calcul d'itiniraire + if (inputToll.addEventListener) { + inputToll.addEventListener("change", function (e) { + context.onRouteExclusionsChange(e); + }); + } else if (inputToll.attachEvent) { + inputToll.attachEvent("onchange", function (e) { + context.onRouteExclusionsChange(e); + }); + } + div.appendChild(inputToll); + + var labelToll = document.createElement("label"); + labelToll.className = "GProuteExclusionsOption"; + labelToll.htmlFor = this._addUID("GProuteExclusionsToll"); + labelToll.innerHTML = "Péages"; + div.appendChild(labelToll); + break; + + case "tunnel": + var inputTunnel = document.createElement("input"); + inputTunnel.id = this._addUID("GProuteExclusionsTunnel"); + inputTunnel.type = "checkbox"; + inputTunnel.value = "Tunnel"; + inputTunnel.checked = !status; + // gestionnaire d'evenement : + // on stocke l'exclusion, + // utilisation pour la requête sur le service de calcul d'itiniraire + if (inputTunnel.addEventListener) { + inputTunnel.addEventListener("change", function (e) { + context.onRouteExclusionsChange(e); + }); + } else if (inputTunnel.attachEvent) { + inputTunnel.attachEvent("onchange", function (e) { + context.onRouteExclusionsChange(e); + }); + } + div.appendChild(inputTunnel); + + var labelTunnel = document.createElement("label"); + labelTunnel.className = "GProuteExclusionsOption"; + labelTunnel.htmlFor = this._addUID("GProuteExclusionsTunnel"); + labelTunnel.innerHTML = "Tunnels"; + div.appendChild(labelTunnel); + break; + + case "bridge": + var inputBridge = document.createElement("input"); + inputBridge.id = this._addUID("GProuteExclusionsBridge"); + inputBridge.type = "checkbox"; + inputBridge.value = "Bridge"; + inputBridge.checked = !status; + // gestionnaire d'evenement : + // on stocke l'exclusion, + // utilisation pour la requête sur le service de calcul d'itiniraire + if (inputBridge.addEventListener) { + inputBridge.addEventListener("change", function (e) { + context.onRouteExclusionsChange(e); + }); + } else if (inputBridge.attachEvent) { + inputBridge.attachEvent("onchange", function (e) { + context.onRouteExclusionsChange(e); + }); + } + div.appendChild(inputBridge); + + var labelBridge = document.createElement("label"); + labelBridge.className = "GProuteExclusionsOption"; + labelBridge.htmlFor = this._addUID("GProuteExclusionsBridge"); + labelBridge.innerHTML = "Ponts"; + div.appendChild(labelBridge); + break; + } + } + } + + return div; + }, + + // ################################################################### // + // ############################### Submit Form ####################### // + // ################################################################### // + + /** + * Create Submit Form Element + * + * @returns {DOMElement} DOM element + */ + _createRouteSubmitFormElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GProuteSubmit"); + input.className = "GPinputSubmit"; + input.type = "submit"; + input.value = "Calculer"; + + return input; + }, + + // ################################################################### // + // ############################### Reset picto ####################### // + // ################################################################### // + + /** + * Create Reset Picto Element + * + * @returns {DOMElement} DOM element + */ + _createRouteFormResetElement : function () { + var self = this; + + var divReset = document.createElement("div"); + divReset.id = this._addUID("GProuteReset"); + divReset.title = "Réinitialiser les paramètres"; + divReset.addEventListener("click", function (e) { + self.onRouteResetClick(e); + }); + + return divReset; + } +}; + +export default RouteDOM; diff --git a/src/Common-review/Controls/ScaleDOM.js b/src/Common-review/Controls/ScaleDOM.js new file mode 100644 index 000000000..826eb2a8f --- /dev/null +++ b/src/Common-review/Controls/ScaleDOM.js @@ -0,0 +1,26 @@ +var ScaleDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPscaleContainer"); + container.className = "GPwidget"; + return container; + } +}; + +export default ScaleDOM; diff --git a/src/Common-review/Controls/SearchEngineDOM.js b/src/Common-review/Controls/SearchEngineDOM.js new file mode 100644 index 000000000..c9dfbb5b7 --- /dev/null +++ b/src/Common-review/Controls/SearchEngineDOM.js @@ -0,0 +1,747 @@ +import ID from "../Utils/SelectorID"; + +var SearchEngineDOM = { + + /** + * Add uuid to the tag ID + * @param {String} id - id selector + * @returns {String} uid - id selector with an unique id + */ + _addUID : function (id) { + var uid = (this._uid) ? id + "-" + this._uid : id; + return uid; + }, + + /** + * Main container (DOM) + * + * @returns {DOMElement} DOM element + */ + _createMainContainerElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPsearchEngine"); + container.className = "GPwidget"; + return container; + }, + + // ################################################################### // + // ################### Methods of main container ##################### // + // ################################################################### // + + /** + * Hidden checkbox for minimizing/maximizing + * + * @returns {DOMElement} DOM element + */ + _createShowSearchEngineElement : function () { + var input = document.createElement("input"); + input.id = this._addUID("GPshowSearchEngine"); + input.type = "checkbox"; + return input; + }, + + /** + * Show search engine + * + * @returns {DOMElement} DOM element + */ + _createShowSearchEnginePictoElement : function () { + // contexte d'execution + var self = this; + + var label = document.createElement("label"); + label.id = this._addUID("GPshowSearchEnginePicto"); + label.className = "GPshowAdvancedToolPicto"; + label.htmlFor = this._addUID("GPshowSearchEngine"); + label.title = "Afficher/masquer la recherche par lieux"; + + // Close all results and panels when minimizing the widget + label.addEventListener("click", function () { + document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none"; + document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none"; + var showAdvancedSearch = document.getElementById(self._addUID("GPshowAdvancedSearch")); + if (showAdvancedSearch) { + showAdvancedSearch.style.display = null; + document.getElementById(self._addUID("GPadvancedSearchPanel")).style.display = "none"; + } + var id = "#GPsearchInput-" + self._uid; + document.querySelector(id + " input").disabled = false; // FIXME form[id^=GPsearchInput] = #GPsearchInput ? + self.onShowSearchEngineClick(); + }); + + var spanOpen = document.createElement("span"); + spanOpen.id = this._addUID("GPshowSearchEngineOpen"); + spanOpen.className = "GPshowAdvancedToolOpen"; + label.appendChild(spanOpen); + + return label; + }, + + /** + * Simple search input + * @param {String} placeholder - placeholder + * + * @returns {DOMElement} DOM element + */ + _createSearchInputElement : function (placeholder) { + // contexte d'execution + var self = this; + + var form = document.createElement("form"); + form.id = this._addUID("GPsearchInput"); + // Open geocode results panel when submitting the input + form.addEventListener("submit", function (e) { + e.preventDefault(); + document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "block"; + document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none"; + // cf. FIXME + // document.querySelector("#GPsearchInput input").blur (); + + // gestionnaire d'evenement : + // on récupère la valeur de saisie pour requête sur le service de geocodage + self.onGeocodingSearchSubmit(e); + return false; + }); + + var input = document.createElement("input"); + input.id = this._addUID("GPsearchInputText"); + input.type = "text"; + input.placeholder = placeholder; + input.autocomplete = "off"; + // Manage autocomplete list appearance when filling the address input + input.addEventListener("keyup", function (e) { + var charCode = e.which || e.keyCode; + if (charCode === 13 || charCode === 10 || charCode === 38 || charCode === 40) { + return; + } + document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none"; + if (input.value.length > 2) { + document.getElementById(self._addUID("GPautoCompleteList")).style.display = "block"; + } else { + document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none"; + } + // gestionnaire d'evenement : + // on récupère la valeur de saisie pour requête sur le service d'autocompletion + self.onAutoCompleteSearchText(e); + }); + + // FIXME ce code interfere avec le click sur la liste des suggested locations ! + // input.addEventListener("blur", function(e) { + // document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none"; + // }); + + input.addEventListener("keydown", function (e) { + // FIXME + // l'action clavier 'enter (13)' lance le submit de la form ! + // Ce comportement n'est pas souhaité car le submit execute un geocodage ! + // Il faut donc trouver le moyen d'eviter le submit sur un return venant + // seulement d'une selection de suggestion... + + var charCode = e.which || e.keyCode; + + var container = document.getElementById(self._addUID("GPautocompleteResults")); + + // si aucun container !? + if (!container) { + return; + } + + var curr = container.getElementsByClassName("GPautoCompleteProposal current"); + var list = container.getElementsByClassName("GPautoCompleteProposal"); + + // si aucune suggestion, on ne va pas plus loin ! + var length = list.length; + if (!length) { + return; + } + + var current = null; + + // si aucun item courant, on prend le 1er ! + if (!curr.length) { + current = list[0]; + current.className = "GPautoCompleteProposal current"; + current.style.color = "#000000"; + current.style["background-color"] = "#CEDBEF"; + return; + } else { + current = curr[0]; + } + + var index = parseInt(ID.index(current.id), 10); + var next = (index === length - 1) ? list[0] : list[index + 1]; + var prev = (index === 0) ? list[length - 1] : list[index - 1]; + + current.style["background-color"] = ""; + current.style.color = ""; + prev.style["background-color"] = ""; + prev.style.color = ""; + next.style["background-color"] = ""; + next.style.color = ""; + + switch (charCode) { + case 38: // arrow up + current.className = "GPautoCompleteProposal"; + prev.className = "GPautoCompleteProposal current"; + prev.style.color = "#000000"; + prev.style["background-color"] = "#CEDBEF"; + break; + case 40: // arrow down + current.className = "GPautoCompleteProposal"; + next.className = "GPautoCompleteProposal current"; + next.style.color = "#000000"; + next.style["background-color"] = "#CEDBEF"; + break; + case 13: // enter + // cf. FIXME + e.preventDefault(); + current.click(e); + break; + } + + current.focus(); + }); + + form.appendChild(input); + + var div = document.createElement("div"); + div.id = this._addUID("GPsearchInputReset"); + // Reset input + div.addEventListener("click", function () { + document.getElementById(self._addUID("GPsearchInputText")).value = ""; + document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none"; + document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none"; + self.onSearchResetClick(); + }); + form.appendChild(div); + + return form; + }, + + /** + * Show advanced search panel + * + * @returns {DOMElement} DOM element + */ + _createShowAdvancedSearchElement : function () { + // contexte d'execution + var self = this; + + var div = document.createElement("div"); + div.id = this._addUID("GPshowAdvancedSearch"); + div.className = "GPshowAdvancedToolPicto"; + div.title = "Ouvrir la recherche avancée"; + + // Open advanced search + div.addEventListener("click", function () { + var id = "#GPsearchInput-" + self._uid; + document.querySelector(id + " input").disabled = true; + document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none"; + document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none"; + document.getElementById(self._addUID("GPshowAdvancedSearch")).style.display = "none"; + document.getElementById(self._addUID("GPadvancedSearchPanel")).style.display = "inline-block"; + }); + + var span = document.createElement("span"); + span.id = this._addUID("GPshowAdvancedSearchOpen"); + span.className = "GPshowAdvancedToolOpen"; + div.appendChild(span); + + return div; + }, + + /** + * Advanced search panel + * + * FIXME + * don't call this._createAdvancedSearchPanelHeaderElement + * don't call this._createAdvancedSearchPanelFormElement + * + * @returns {DOMElement} DOM element + */ + _createAdvancedSearchPanelElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPadvancedSearchPanel"); + div.className = "GPpanel"; + div.style.display = "none"; + + // FIXME on decompose la fonction pour les besoins du controle, + // on ajoutera ces childs à la main... + // div.appendChild(this._createAdvancedSearchPanelHeaderElement ()); + // div.appendChild(this._createAdvancedSearchPanelFormElement ()); + + return div; + }, + + /** + * Geocoding results + * + * FIXME + * don't call this._createGeocodeResultsListElement + * + * @returns {DOMElement} DOM element + */ + _createGeocodeResultsElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPgeocodeResultsList"); + div.className = "GPpanel"; + div.style.display = "none"; + + div.appendChild(this._createGeocodeResultsHeaderElement()); + + // FIXME on decompose la fonction pour les besoins du controle, + // on ajoutera ces childs à la main... + // div.appendChild(this._createGeocodeResultsListElement ()); + + return div; + }, + + /** + * Autocompletion results + * + * FIXME + * don't call this._createAutoCompleteListElement + * + * @returns {DOMElement} DOM element + */ + _createAutoCompleteElement : function () { + var div = document.createElement("div"); + div.id = this._addUID("GPautoCompleteList"); + div.className = "GPautoCompleteList"; // GPpanel ? + div.style.display = "none"; + + // FIXME on decompose la fonction pour les besoins du controle, + // on ajoutera ces childs à la main... + // div.appendChild(this._createAutoCompleteListElement ()); + + return div; + }, + + // ################################################################### // + // ################### Autocompletion container ###################### // + // ################################################################### // + + /** + * Autocompletion results list. + * + * @returns {DOMElement} DOM element + */ + _createAutoCompleteListElement : function () { + // contexte d'execution + var self = this; + + var container = document.createElement("div"); + container.id = this._addUID("GPautocompleteResults"); + + if (container.addEventListener) { + container.addEventListener("click", function (e) { + self.onAutoCompletedResultsItemClick(e); + document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none"; + }, false); + } else if (container.attachEvent) { + container.attachEvent("onclick", function (e) { + self.onAutoCompletedResultsItemClick(e); + document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none"; + }); + } + + // Proposals are dynamically filled in Javascript by autocomplete service + //
...
+ + return container; + }, + + /** + * Autocompletion result. + * Proposals are dynamically filled in Javascript by autocomplete service + * + * TODO formaliser le contenu des reponse + * + * @param {Object} location - suggested or geocoded location results + * @param {Number} id - ID + */ + _createAutoCompletedLocationElement : function (location, id) { + var container = document.getElementById(this._addUID("GPautocompleteResults")); + + var div = document.createElement("div"); + div.id = this._addUID("AutoCompletedLocation_" + id); + div.className = "GPautoCompleteProposal"; + div.innerHTML = location.fullText; + if (div.addEventListener) { + div.addEventListener("click", function (e) { + container.click(e); + }, false); + } else if (div.attachEvent) { + div.attachEvent("onclick", function (e) { + container.click(e); + }); + } + + container.appendChild(div); + }, + + // ################################################################### // + // ############### Geocoding with advanced container ################# // + // ################################################################### // + + /** + * @returns {DOMElement} DOM element + */ + _createAdvancedSearchPanelHeaderElement : function () { + // contexte d'execution + var self = this; + + var container = document.createElement("div"); + container.className = "GPpanelHeader"; + + var divTitle = document.createElement("div"); + divTitle.className = "GPpanelTitle"; + divTitle.innerHTML = "Recherche avancée"; + container.appendChild(divTitle); + + var divClose = document.createElement("div"); + divClose.id = this._addUID("GPadvancedSearchClose"); + divClose.className = "GPpanelClose"; + divClose.title = "Fermer la recherche avancée"; + + if (divClose.addEventListener) { + divClose.addEventListener("click", function () { + var id = "#GPsearchInput-" + self._uid; + document.querySelector(id + " input").disabled = false; + document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none"; + document.getElementById(self._addUID("GPshowAdvancedSearch")).style.display = "inline-block"; + document.getElementById(self._addUID("GPadvancedSearchPanel")).style.display = "none"; + }, false); + } else if (divClose.attachEvent) { + divClose.attachEvent("onclick", function () { + var id = "#GPsearchInput-" + self._uid; + document.querySelector(id + " input").disabled = false; + document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none"; + document.getElementById(self._addUID("GPshowAdvancedSearch")).style.display = "inline-block"; + document.getElementById(self._addUID("GPadvancedSearchPanel")).style.display = "none"; + }); + } + + container.appendChild(divClose); + + return container; + }, + + /** + * @param {Object[]} advancedSearchCodes - codes + * + * @returns {DOMElement} DOM element + */ + _createAdvancedSearchPanelFormElement : function (advancedSearchCodes) { + // contexte d'execution + var self = this; + + var form = document.createElement("form"); + form.id = this._addUID("GPadvancedSearchForm"); + form.addEventListener("submit", function (e) { + e.preventDefault(); + // data + var data = []; + // liste des attributs de la ressource de geocodage + var id = "#GPadvancedSearchFilters-" + self._uid; + var matchesFilters = document.querySelectorAll(id + " > div > div > input"); + for (var i = 0; i < matchesFilters.length; i++) { + var element = matchesFilters[i]; + data.push({ + key : element.name, + value : element.value + }); + } + + // gestionnaire d'evenement : + // on récupère les valeurs de saisies pour requête sur le service de geocodage + self.onGeocodingAdvancedSearchSubmit(e, data); + document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "block"; + + return false; + }); + + var div = document.createElement("div"); + div.className = "GPflexInput"; + + var label = document.createElement("label"); + label.className = "GPadvancedSearchCodeLabel"; + label.innerHTML = "Recherche par"; + div.appendChild(label); + + var select = this._createAdvancedSearchFormCodeElement(advancedSearchCodes); + div.appendChild(select); + + // FIXME on decompose la fonction pour les besoins du controle, + // on ajoutera ces childs à la main... + + // var filters = this._createAdvancedSearchFormFiltersElement (); + // form.appendChild(filters); + + // var input = this._createAdvancedSearchFormInputElement (); + // form.appendChild(input); + + form.appendChild(div); + + return form; + }, + + /** + * @param {Object[]} codes - codes + * @returns {DOMElement} DOM element + */ + _createAdvancedSearchFormCodeElement : function (codes) { + // contexte d'execution + var self = this; + + var select = document.createElement("select"); + select.id = this._addUID("GPadvancedSearchCode"); + select.className = "GPadvancedSearchCode"; + select.addEventListener("change", function (e) { + // var idx = e.target.selectedIndex; + // var value = e.target.options[idx].value; + // gestionnaire d'evenement : + // permet de recuperer des informations diverses... + self.onGeocodingAdvancedSearchCodeChange(e); + }, false); + + // liste statique au cas où des codes n'ont pas été passés en entrée + if (!codes) { + codes = [{ + id : "PositionOfInterest", + title : "Lieux/toponymes" + }, { + id : "StreetAddress", + title : "Adresses" + }, { + id : "CadastralParcel", + title : "Parcelles cadastrales" + }, { + id : "Administratif", + title : "Administratif" + }]; + } + + for (var i = 0; i < codes.length; i++) { + var option = document.createElement("option"); + option.value = codes[i].id; + option.text = codes[i].title; + select.appendChild(option); + } + + return select; + }, + + /** + * @returns {DOMElement} DOM element + */ + _createAdvancedSearchFormInputElement : function () { + var input = document.createElement("input"); + input.type = "submit"; + input.id = this._addUID("GPadvancedSearchSubmit"); + input.className = "GPinputSubmit"; + input.value = "Chercher"; + + return input; + }, + + /** + * Filters geocoding. + * + * @returns {DOMElement} DOM element + */ + _createAdvancedSearchFormFiltersElement : function () { + var container = document.createElement("div"); + container.id = this._addUID("GPadvancedSearchFilters"); + return container; + }, + + /** + * Create filter container for resources : + * "PositionOfInterest", "StreetAddress", ... + * + * @param {String} code - code of geocoding resource + * @param {Boolean} display - display + * + * @returns {DOMElement} DOM element + */ + _createAdvancedSearchFiltersTableElement : function (code, display) { + var container = document.createElement("div"); + container.id = this._addUID(code); + if (!display) { + container.style.display = "none"; + } + + return container; + }, + + /** + * Create filter attribut for a resource : + * "PositionOfInterest", "StreetAddress", ... + * Research filters are filled in Javascript depending on developer choice + * + * @param {Object} filterAttributes - filter attributes : + * @param {String} filterAttributes.code - code of geocoding resource + * @param {String} filterAttributes.name - ID + * @param {String} filterAttributes.title - label + * @param {String} filterAttributes.description - description + * @param {String} filterAttributes.value - value + * + * @returns {DOMElement} DOM element + */ + _createAdvancedSearchFiltersAttributElement : function (filterAttributes) { + // INFORMATION + // cette methode peut être appelée si le document n'existe pas, elle + // permet ainsi de creer une div sans insertion dans le container... + + var container = null; + var name = filterAttributes.name; + var title = filterAttributes.title; + var description = filterAttributes.description; + var code = filterAttributes.code; + var value = filterAttributes.value; + + var div = document.createElement("div"); + div.className = "GPflexInput"; + + var label = document.createElement("label"); + label.className = "GPadvancedSearchFilterLabel"; + label.htmlFor = name; + label.title = description || title; + label.innerHTML = title; + div.appendChild(label); + + var input = document.createElement("input"); + input.id = name; + input.className = "GPadvancedSearchFilterInput"; + input.type = "text"; + input.name = name; + if (value) { + input.value = value; + } + div.appendChild(input); + + container = document.getElementById(this._addUID(code)); + + if (container) { + container.appendChild(div); + } else { + // le container, c'est la div ! + container = div; + } + + return container; + }, + + // ################################################################### // + // ################## Geocoding results container #################### // + // ################################################################### // + + /** + * @returns {DOMElement} DOM element + */ + _createGeocodeResultsHeaderElement : function () { + var self = this; + + var container = document.createElement("div"); + container.className = "GPpanelHeader"; + + var divTitle = document.createElement("div"); + divTitle.className = "GPpanelTitle"; + divTitle.innerHTML = "Résultats de la recherche"; + container.appendChild(divTitle); + + var divClose = document.createElement("div"); + divClose.id = this._addUID("GPgeocodeResultsClose"); + divClose.className = "GPpanelClose"; + divClose.title = "Fermer la fenêtre de résultats"; + + if (divClose.addEventListener) { + divClose.addEventListener("click", function () { + document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none"; + }, false); + } else if (divClose.attachEvent) { + divClose.attachEvent("onclick", function () { + document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none"; + }); + } + container.appendChild(divClose); + + return container; + }, + + /** + * Geocoding results list. + * + * @returns {DOMElement} DOM element + */ + _createGeocodeResultsListElement : function () { + // contexte d'execution + var self = this; + + var container = document.createElement("div"); + container.id = this._addUID("GPgeocodeResults"); + + if (container.addEventListener) { + container.addEventListener("click", function (e) { + if (!e.ctrlKey) { + document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none"; + } + self.onGeocodedResultsItemClick(e); + }, false); + } else if (container.attachEvent) { + container.attachEvent("onclick", function (e) { + if (!e.ctrlKey) { + document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none"; + } + self.onGeocodedResultsItemClick(e); + }); + } + // Results are dynamically filled in Javascript by geocoding service + //
...
+ + return container; + }, + + /** + * Geocoding result. + * Results are dynamically filled in Javascript by geocoding service + * + * TODO formaliser le contenu des reponses + * FIXME formater la reponse en amont ! + * + * @param {Object} location - suggested or geocoded location results + * @param {Number} id - ID + */ + _createGeocodedLocationElement : function (location, id) { + var container = document.getElementById(this._addUID("GPgeocodeResults")); + + var div = document.createElement("div"); + div.id = this._addUID("GeocodedLocation_" + id); + div.className = "GPautoCompleteProposal"; + + if (typeof location === "string") { + div.innerHTML = location; + } else { + var places = location.placeAttributes; + + if (places.freeform) { + // reponse en freeForm + div.innerHTML = places.freeform; + } else if (places.postalCode) { + // cas des StreetAddress, PositionOfInterest, Administratif + // on affiche uniquement ce qui est commun aux ressources ... + div.innerHTML = places.postalCode + " " + places.commune; + } else if (places.cadastralParcel) { + // cas des CadastralParcel + div.innerHTML = places.cadastralParcel; + } else { + div.innerHTML = "..."; + } + } + + container.appendChild(div); + } +}; + +export default SearchEngineDOM; diff --git a/src/Common-review/Styles.js b/src/Common-review/Styles.js new file mode 100644 index 000000000..ad280fa0f --- /dev/null +++ b/src/Common-review/Styles.js @@ -0,0 +1,17 @@ +import "./CSS/GPboostRelief.css"; +import "./CSS/GPdrawing.css"; +import "./CSS/GPelevationPath.css"; +import "./CSS/GPgeneralWidget.css"; +import "./CSS/GPgetFeatureInfo.css"; +import "./CSS/GPisochron.css"; +import "./CSS/GPlayerSwitcher.css"; +import "./CSS/GPlocation.css"; +import "./CSS/GPmeasureArea.css"; +import "./CSS/GPmeasureAzimuth.css"; +import "./CSS/GPmeasureLength.css"; +import "./CSS/GPmeasureToolTip.css"; +import "./CSS/GPmousePosition.css"; +import "./CSS/GPreverseGeocoding.css"; +import "./CSS/GProute.css"; +import "./CSS/GPsearchEngine.css"; +import "./CSS/GPwaiting.css"; diff --git a/src/Common-review/Utils.js b/src/Common-review/Utils.js new file mode 100644 index 000000000..a303fb92c --- /dev/null +++ b/src/Common-review/Utils.js @@ -0,0 +1,98 @@ +/** +* @module Utils +* @alias Gp.olUtils +* @description +* ... +* +* @example +* detectSupport(); +* assign(); +* mergeParams(); +*/ +var Utils = { + + /** + * this method is called by the constructor. + * this information is useful to switch to touch mode. + * Detection : test for desktop or tactile + * + * @returns {Boolean} isDesktop - true for desktop userAgent, false for mobile + */ + detectSupport : function () { + var isDesktop = true; + var userAgent = window.navigator.userAgent.toLowerCase(); + + if (userAgent.indexOf("iphone") !== -1 || + userAgent.indexOf("ipod") !== -1 || + userAgent.indexOf("ipad") !== -1 || + userAgent.indexOf("android") !== -1 || + userAgent.indexOf("mobile") !== -1 || + userAgent.indexOf("blackberry") !== -1 || + userAgent.indexOf("tablet") !== -1 || + userAgent.indexOf("phone") !== -1 || + userAgent.indexOf("touch") !== -1) { + isDesktop = false; + } + + if (userAgent.indexOf("msie") !== -1 || + userAgent.indexOf("trident") !== -1) { + isDesktop = true; + } + + return isDesktop; + }, + + /** + * Copies all source object members to dest + * + * @param {Object} dest - destination object where properties and method will be copied + * @param {Object} source - source object from which properties and method will be copied + * @returns {Object} dest + */ + assign : function (dest, source) { + dest = dest || {}; + for (var prop in source) { + if (source.hasOwnProperty(prop)) { + dest[prop] = source[prop]; + } + } + return dest; + }, + + /** + * Merge two objects parameters (deeper than assign) + * + * @param {Object} dest - destination object where properties and method will be merge + * @param {Object} source - source object from which properties and method will be merge + * @param {Boolean} replace - replace destination value by source if exists or not (true by default) + */ + mergeParams : function (dest, source, replace) { + if (!dest || !source) { + return; + } + if (typeof replace === "undefined") { + replace = true; + } + for (var param in source) { + if (source.hasOwnProperty(param)) { + if (typeof source[param] === "object") { + if (dest.hasOwnProperty(param)) { + this.mergeParams(dest[param], source[param], replace); + } else { + dest[param] = source[param]; + } + } else { + if (dest.hasOwnProperty(param)) { + if (replace) { + dest[param] = source[param]; + } + } else { + dest[param] = source[param]; + } + } + } + } + } +}; + +export default Utils; diff --git a/src/Common-review/Utils/AutoLoadConfig.js b/src/Common-review/Utils/AutoLoadConfig.js new file mode 100644 index 000000000..36122b19b --- /dev/null +++ b/src/Common-review/Utils/AutoLoadConfig.js @@ -0,0 +1,58 @@ +import Gp from "geoportal-access-lib"; + +(function () { + var scripts = document.getElementsByTagName("script"); + + var key = scripts[scripts.length - 1].getAttribute("data-key"); + // in case of several keys + if (key) { + var splitKeys = key.split(/;|,|\|/); + if (key && splitKeys.length > 1) { + var keys = []; + for (var i = 0; i < splitKeys.length; i++) { + keys.push(splitKeys[i]); + } + key = keys; + } + } + var url = scripts[scripts.length - 1].getAttribute("data-url"); + var timeout = scripts[scripts.length - 1].getAttribute("data-timeout"); + + // callback + var success = function () { + // Pas de messages en mode prod + // console.log("GetConfig success!"); + }; + + // callback + var error = function (e) { + throw new Error("Configuration load failed : " + e.message); + }; + + if (!key && !url) { + // pas de message d'information ! + // console.log("WARNING : parameters missing 'data-key' and 'data-url', the loading of configuration can not be done !"); + return; + } + + var options = { + apiKey : key, + onSuccess : success, + onFailure : error + }; + + if (url) { + options.serverUrl = url; + options.callbackSuffix = ""; + } + + if (timeout) { + options.timeOut = timeout; + } + + // test d'existance de la varibale globale Gp.Config + if (!Gp.Config) { + // appel du service + Gp.Services.getConfig(options); + } +})(); diff --git a/src/Common-review/Utils/CheckRightManagement.js b/src/Common-review/Utils/CheckRightManagement.js new file mode 100644 index 000000000..e6c2a1b16 --- /dev/null +++ b/src/Common-review/Utils/CheckRightManagement.js @@ -0,0 +1,172 @@ +import Logger from "../../Common/Utils/LoggerByDefault"; +import Config from "./Config"; + +export default { + /** + * Contrôle des droits sur les ressources. + * + * @param {Object} options - liste des options + * @param {String} options.key - clef API + * @param {Array} options.resources - liste des ressources + * @param {Array} options.services - liste des services + * @returns {Object} rightManagement - undefined ou { + * key : "", + * service-1 : [resource-1, resource-2], + * service-2 : [resource-1, resource-2] + * } + */ + check : function (options) { + // logger + + var logger = Logger.getLogger("checkrightmanagement"); + + // si aucune option n'est renseignée... + if (!options) { + // message orienté pour le developpeur ! + logger.error("WARNING : " + + "no parameter specified !"); + return; + } + + // les options + var _key = options.key; + var _resources = options.resources || []; + var _services = options.services || []; + + // si aucune information sur les ressources, + // il est impossible de controler quelquechose !!! + if (!_resources || _resources.length === 0) { + // message orienté pour le developpeur ! + logger.error("WARNING : " + + "no parameter 'resources' specified !"); + return; + } + + // si aucune information sur les services, + // il est impossible de controler quelquechose !!! + if (!_services || _services.length === 0) { + // message orienté pour le developpeur ! + logger.error("WARNING : " + + "no parameter 'services' specified !"); + return; + } + + // les ressources controlées : + // Ex. + // { + // "Itineraire" : ["Pieton", "Voiture"], + // "Geocode" : ["PositionOfInterest", "StreetAddress", "CadastralParcel", "Administratif"], + // "AutoCompletion" : ["PositionOfInterest", "StreetAddress", "CadastralParcel", "Administratif"], + // "Elevation" : ["SERVICE_CALCUL_ALTIMETRIQUE_RSC"] + // } + var _rightManagement = {}; + + // la clef API n'est pas renseignée + if (!_key) { + // on verifie si l'autoconfiguration est disponible + + if (!Config.isConfigLoaded()) { + // si l'autoconfiguration n'est pas chargée, + // aucune vérification des droits est possible... + + logger.warn("WARNING : " + + "The 'apiKey' parameter is missing, " + + "and the contract key configuration has not been loaded, " + + "so impossible to check yours rights !"); + + return; + } else { + // si l'autoconfiguration est chargée, + // on recupere la clef API, et on en profitera ensuite pour controler + // les droits sur les ressources. + + // FIXME par defaut, on recupere toujours la première... + _key = Object.keys(Config.configuration.generalOptions.apiKeys)[0]; + logger.log(_key); + } + } + + // la clef API est renseignée ou recuperée de l'autoconfiguration + if (_key) { + // on verifie si l'autoconfiguration est disponible + + if (!Config.isConfigLoaded()) { + // si l'autoconfiguration n'est pas chargée, + // il est toujours possible de requeter le service avec une clef API, + // mais les droits sur les ressources ne sont pas garantis, on risque + // d'obtenir des erreurs 403 forbidden... + // la responsabilité revient à l'utilisateur (message d'information)... + + logger.warn("WARNING : " + + "the contract key configuration has not been loaded, " + + "so be carefull !"); + + // les ressouces non controlées + var _noRightManagement = {}; + + for (var i = 0; i < _services.length; i++) { + var service = _services[i]; + _noRightManagement[service] = []; + + for (var j = 0; j < _resources.length; j++) { + var resource = _resources[j]; + _noRightManagement[service].push(resource); + } + } + + // on ajoute la clef + _noRightManagement.key = _key; + + logger.log("right management not checked", _noRightManagement); + + return _noRightManagement; + } else { + // si l'autoconf est chargée, + // on verifie la correspondance entre la clef et l'autoconfiguration, + // on previent l'utilisateur (message d'information) s'il n'a + // pas de droits sur certaines ressources ... + + // doit on ecarter les ressources sans droit ? + // oui, si possible avec un message d'information pour l'utilisateur... + + for (var k = 0; k < _resources.length; k++) { + var _resource = _resources[k]; + + for (var l = 0; l < _services.length; l++) { + var _service = _services[l]; + + var params = Config.getServiceParams(_resource, _service, _key); + if (!params || Object.keys(params).length === 0) { + logger.warn("WARNING : " + + "The contract key configuration has no rights to load this geoportal " + + "resource (" + _resource + ") " + + "for this service (" + _service + ") "); + continue; + } + + if (!_rightManagement[_service]) { + _rightManagement[_service] = []; + } + + _rightManagement[_service].push(_resource); + } + } + + if (!_rightManagement || Object.keys(_rightManagement).length === 0) { + logger.warn("WARNING : " + + "The contract key configuration has been loaded, " + + "and the 'apiKey' parameter has been set, " + + "but, there is a problem on the mapping between the contract and the key !"); + return; + } + + // on ajoute la clef + _rightManagement.key = _key; + + logger.log("right management checked", _rightManagement); + + return _rightManagement; + } + } + } +}; diff --git a/src/Common-review/Utils/ColorUtils.js b/src/Common-review/Utils/ColorUtils.js new file mode 100644 index 000000000..3b51b62c2 --- /dev/null +++ b/src/Common-review/Utils/ColorUtils.js @@ -0,0 +1,75 @@ +/** +* @module ColorUtils +* @alias Gp.ColorUtils +* @description +* ... +* +* @example +* rgbaToHex(); +* hexToRgba(); +*/ +var ColorUtils = { + /** + * Converts rgba String to #RRGGBBAA + * (Code adapted from : https://gist.github.com/mstssk/afda4ce9e5c335fd79cd) + * + * @param {String} rgba - A color of RGB or RGBA format. + * @returns {Object} hex and opacity formated values + */ + rgbaToHex : function (rgba) { + // number to hex conversion + function hex (number) { + if (number > 255) { + throw new Error("'" + number + "'' is greater than 255(0xff);"); + } + var str = Number(number).toString(16); + return ("0" + str).slice(-2); + } + var regex = /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(0?.?\d+)\s*)?\)/; + var parsed = regex.exec(rgba); + if (!parsed) { + throw new Error("Invalid format: " + rgba); + } + var red = parsed[1]; + var green = parsed[2]; + var blue = parsed[3]; + var alpha = parsed[4]; + var elems = [hex(red), hex(green), hex(blue)]; + var result = {}; + result.hex = "#" + elems.join(""); + if (alpha) { + // elems.push(hex(alpha)); + result.opacity = parseFloat(alpha); + } + return result; + }, + + /** + * Converts hex color and opacity value to rgba String. + * (Code adapted from : http://stackoverflow.com/a/5624139) + * @param {String} hex - A color value on RGB format (hexa). + * @param {Number} opacity - A opacity value. + * @returns {String} A color of RGB or RGBA format + */ + hexToRgba : function (hex, opacity) { + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + if (!hex) { + throw new Error("Invalid format"); + } + hex = hex.replace(shorthandRegex, function (m, r, g, b) { + return r + r + g + g + b + b; + }); + + var rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + rgb = rgb ? { + r : parseInt(rgb[1], 16), + g : parseInt(rgb[2], 16), + b : parseInt(rgb[3], 16) + } : null; + var result = rgb ? "rgba(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ", " + opacity + ")" : null; + return result; + } +}; + +export default ColorUtils; diff --git a/src/Common-review/Utils/Config.js b/src/Common-review/Utils/Config.js new file mode 100644 index 000000000..fc63876f4 --- /dev/null +++ b/src/Common-review/Utils/Config.js @@ -0,0 +1,265 @@ +import Logger from "../../Common/Utils/LoggerByDefault"; + +var logger = Logger.getLogger("config"); + +var Config = { + + /** autoconf */ + configuration : null, + + /** + * Controle du chargement de l'autoconf + * + * @returns {Boolean} isConfigLoaded - True si l'autoconf a déjà été chargée, False sinon. + */ + isConfigLoaded : function () { + var scope = typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : {}; + if (scope.Gp && scope.Gp.Config && Object.keys(scope.Gp.Config).length !== 0) { + this.configuration = scope.Gp.Config; + return true; + } + return false; + }, + + /** + * Recuperation de l'identifiant d'une couche donnée + * + * @param {String} layerName - nom de la couche (par ex. "ORTHOIMAGERY.ORTHOPHOTOS") + * @param {String} service - nom du service (par ex. "WMS" ou "WMTS") + * @returns {String} layerId - identifiant de la couche (par ex. "ORTHOIMAGERY.ORTHOPHOTOS$GEOPORTAIL:OGC:WMTS") + */ + getLayerId : function (layerName, service) { + var layerId = null; + + // layer + // key : [layerName]$[contexte]:OGC:[service] + // ex : "ORTHOIMAGERY.ORTHOPHOTOS$GEOPORTAIL:OGC:WMTS" + + // service + // key : [layerName]$[contexte];[service] + // ex : PositionOfInterest$OGC:OPENLS;ReverseGeocode + + if (this.configuration) { + var layers = this.configuration["layers"]; + for (var key in layers) { + if (layers.hasOwnProperty(key)) { + var parts = key.split("$"); + if (layerName === parts[0]) { + if (parts[1]) { + var servicePartsLayer = parts[1].split(":"); + var servicePartsService = parts[1].split(";"); + + if (servicePartsService[1] === service) { + layerId = key; + break; + } + if (servicePartsLayer[2] === service) { + layerId = key; + break; + } + } + } + } + } + } + if (!layerId) { + logger.error("ERROR layer id (layer name: " + layerName + " / service: " + service + ") was not found !?"); + } + + return layerId; + }, + + /** + * Récupération des paramètres nécessaires à l'affichage d'une couche WMS ou WMTS + * + * @param {String} layerName - nom de la couche (par ex. "ORTHOIMAGERY.ORTHOPHOTOS") + * @param {String} service - nom du service (par ex. "WMS" ou "WMTS") + * @param {String} [apiKey] - Clé de contrat API + * @returns {Object} params - paramètres du service (WMS ou WMTS) pour la couche donnée + * @returns {String} params.url - Url du service à requêter pour afficher la couche + * @returns {String} params.version - Version du service + * @returns {String} params.styles - Style par défaut de la couche + * @returns {String} params.format - Format par défaut de la couche + * @returns {String} params.projection - Projection par défaut de la couche + * @returns {Number} params.minScale - Dénominateur d'échelle minimum de la couche + * @returns {Number} params.maxScale - Dénominateur d'échelle maximum de la couche + * @returns {Gp.BBox} params.extent - Etendue de la couche, dans la projection de la couche + * @returns {Array} params.legends - Tableau des légendes associées à la couche + * @returns {Array} params.metadata - Tableau des métadonnées associées à la couche + * @returns {Array} params.originators - Tableau des originators associés à la couche + * @returns {Array} params.title - Nom de la resource, lisible par un humain. + * @returns {Array} params.description - Url de l'image d'aperçu rapide de la ressource. + * @returns {Array} params.quicklookUrl- Tableau des originators associés à la couche + * @returns {String} params.[TMSLink] - Identifiant de la pyramide (TMS), dans le cas d'une couche WMTS + * @returns {Gp.Point} params.[matrixOrigin] - Origine de la matrice (top left corner), dans le cas d'une couche WMTS + * @returns {Array} params.[nativeResolutions] - Tableau regroupant les résolutions de chaque niveau de la matrice, dans le cas d'une couche WMTS + * @returns {Array} params.[matrixIds] - Tableau regroupant les identifiants de chaque niveau de la matrice, dans le cas d'une couche WMTS + */ + getLayerParams : function (layerName, service, apiKey) { + var params = {}; + + if (this.configuration) { + // récupération de l'identifiant complet de la couche. + var layerId = this.getLayerId(layerName, service); + + if (layerId) { + // récupération de l'objet de configuration de la couche + var layerConf = this.configuration.layers[layerId]; + + // controle de la clef + var key = layerConf.apiKeys[0]; + if (apiKey) { + if (apiKey !== key) { + logger.error("ERROR different keys (" + apiKey + " !== " + key + ") !?"); + return; + } + } + + apiKey = apiKey || key; + params.key = apiKey; + // récupération des paramètres du service + params.url = layerConf.getServerUrl(apiKey); + params.version = layerConf.getServiceParams().version; + params.styles = layerConf.getDefaultStyle(); + params.format = layerConf.getDefaultFormat(); + params.projection = layerConf.getDefaultProjection(); + + // récupération des infos de la couche + params.minScale = layerConf.getMinScaleDenominator(); + params.maxScale = layerConf.getMaxScaleDenominator(); + params.extent = layerConf.getBBOX(); + params.legends = layerConf.getLegends(); + params.metadata = layerConf.getMetadata(); + params.originators = layerConf.getOriginators(); + params.title = layerConf.getTitle(); + params.description = layerConf.getDescription(); + params.quicklookUrl = layerConf.getQuicklookUrl(); + + // WMTS : récupération des tileMatrixSetLimits + if (layerConf.wmtsOptions) { + params.tileMatrixSetLimits = layerConf.wmtsOptions.tileMatrixSetLimits; + } + + // WMTS : récupération des paramètres de la pyramide (TMS) + var TMSLink = layerConf.getTMSID(); + if (TMSLink) { + params.TMSLink = TMSLink; + var tmsConf = this.configuration.getTMSConf(TMSLink); + // Get matrix origin : Gp.Point = Object{x:Float, y:Float} + params.matrixOrigin = tmsConf.getTopLeftCorner(); + params.nativeResolutions = tmsConf.nativeResolutions; + params.matrixIds = tmsConf.matrixIds; + params.tileMatrices = tmsConf.tileMatrices; + } + } + } + + return params; + }, + + /** + * Recuperation des parametres d'un service + * + * @param {String} [resource] - "PositionOfInterest", "StreetAddress", "Voiture", "Pieton", ... + * @param {String} [service] - Geocode, Itineraire, ... + * @param {String} [apiKey] - Clé de contrat API + * @returns {Object} params - paramètres de la ressource + * @returns {String} params. - + * @returns {String} params. - + * @returns {String} params. - + */ + getServiceParams : function (resource, service, apiKey) { + var params = {}; + + if (this.configuration) { + // récupération de l'identifiant complet de la couche. + var layerId = this.getLayerId(resource, service); + + if (layerId) { + // récupération de l'objet de configuration de la couche + var layerConf = this.configuration.layers[layerId]; + + // controle de la clef + var key = layerConf.apiKeys[0]; + if (apiKey) { + if (apiKey !== key) { + return; + } + } + + apiKey = apiKey || key; + params.key = apiKey; + // récupération des paramètres du service + params.url = layerConf.getServerUrl(apiKey); + params.version = layerConf.getServiceParams().version; + + // récupération des infos de la couche + params.extent = layerConf.getBBOX(); + params.title = layerConf.getTitle(); + params.description = layerConf.getDescription(); + } + } + + return params; + }, + + /** + * Resolution en geographique + * + * @returns {Array} resolutions + */ + getResolutions : function () { + var resolutions = []; + + if (this.configuration) { + resolutions = this.configuration["generalOptions"]["wgs84Resolutions"]; + } + + return resolutions; + }, + + /** + * Recuperation des parametres TMS de la configuration + * @param {String} tmsName - tile matrix set name + * + * @returns {Object} tile matrix set + */ + getTileMatrix : function (tmsName) { + var tms = {}; + + if (this.configuration) { + if (tmsName) { + tms = this.configuration["tileMatrixSets"][tmsName.toUpperCase()]; + } + } + + return tms; + }, + + /** + * Récupération des contraintes générales d'une couche donnée : extent, minScale, maxScale, projection + * + * @param {String} layerId - identifiant de la couche + * @returns {Object} params - contraintes de la couche + * @returns {String} params.projection - Projection par défaut de la couche + * @returns {Number} params.minScale - Dénominateur d'échelle minimum de la couche + * @returns {Number} params.maxScale - Dénominateur d'échelle maximum de la couche + * @returns {Gp.BBox} params.extent - Etendue de la couche, dans la projection de la couche + */ + getGlobalConstraints : function (layerId) { + var params = {}; + + if (layerId) { + // récupération de l'objet de configuration de la couche + var layerConf = this.configuration.layers[layerId]; + params.projection = layerConf.getDefaultProjection(); + params.minScale = layerConf.getMinScaleDenominator(); + params.maxScale = layerConf.getMaxScaleDenominator(); + params.extent = layerConf.getBBOX(); + } + + return params; + } +}; + +export default Config; diff --git a/src/Common-review/Utils/Draggable.js b/src/Common-review/Utils/Draggable.js new file mode 100644 index 000000000..61920f09e --- /dev/null +++ b/src/Common-review/Utils/Draggable.js @@ -0,0 +1,120 @@ +import Logger from "./LoggerByDefault"; + +var logger = Logger.getLogger("draggable"); + +var Draggable = { + /** + * A draggable HTML element with JavaScript and CSS. + * + * @param {DOMElement} element - element + * @param {DOMElement} header - header (optional) + * @param {DOMElement} container - container (optional) + * @see https://www.w3schools.com/howto/howto_js_draggable.asp + * @see https://stackoverflow.com/questions/52231588/how-to-constrain-div-drag-space-no-jquery + * @example + * // CSS : + * // #element { position: absolute; } + * // HTML : + * //
+ * //
+ * // + * //
+ * // JS : + * var element = document.getElementById("element"); + * Draggable.dragElement(element, header, container); + */ + dragElement : function (element, header, container) { + var offsetX, offsetY; + + var isDragReady = false; + + var dragoffset = { + x : 0, + y : 0 + }; + + if (header) { + header.addEventListener("mousedown", dragMouseDown, true); + } else { + element.addEventListener("mousedown", dragMouseDown, true); + } + + // TODO mettre en place les contraintes + // var constraints = {}; + // if (container) { + // constraints = { + // width : container.clientWidth, + // height : container.clientHeight, + // top : container.offsetTop, + // left : container.offsetLeft + // }; + // } + + function dragMouseDown (e) { + e = e || window.event; + e.preventDefault(); + + isDragReady = true; + + // get the mouse cursor position at startup + e._pageX = e._pageX || e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft); + e._pageY = e._pageY || e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); + dragoffset.x = e._pageX - element.offsetLeft; + dragoffset.y = e._pageY - element.offsetTop; + + document.addEventListener("mouseup", closeDragElement, true); + document.addEventListener("mousemove", elementDrag, true); + } + + function closeDragElement () { + /* stop moving when mouse button is released: */ + isDragReady = false; + document.removeEventListener("mouseup", closeDragElement, true); + document.removeEventListener("mousemove", elementDrag, true); + } + + function elementDrag (e) { + e = e || window.event; + // e.preventDefault(); + + // cf. https://jsfiddle.net/nbbg08mg/2/ + if (isDragReady) { + e._pageX = e._pageX || e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft); + e._pageY = e._pageY || e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); + + var parentLeft = element.parentElement.offsetLeft; + var parentTop = element.parentElement.offsetTop; + logger.trace("parent offset", parentLeft, parentTop); + + // left/right constraint + if (e._pageX - dragoffset.x < 0 - parentLeft) { + offsetX = 0 - parentLeft; + } else if (e._pageX - dragoffset.x + element.clientWidth > document.body.clientWidth) { + offsetX = document.body.clientWidth - element.clientWidth; + } else { + offsetX = e._pageX - dragoffset.x; + } + logger.trace("left/right constraint", offsetX); + + // top/bottom constraint + if (e._pageY - dragoffset.y < 0 - parentTop) { + offsetY = 0 - parentTop; + } else if (e._pageY - dragoffset.y + element.clientHeight > document.body.clientHeight) { + offsetY = document.body.clientHeight - element.clientHeight; + } else { + offsetY = e._pageY - dragoffset.y; + } + logger.trace("top/bottom constraint", offsetY); + + // set the element's new position: + element.style.top = offsetY + "px"; + element.style.left = offsetX + "px"; + } + } + } +}; + +export default Draggable; diff --git a/src/Common-review/Utils/LayerUtils.js b/src/Common-review/Utils/LayerUtils.js new file mode 100644 index 000000000..477f76da9 --- /dev/null +++ b/src/Common-review/Utils/LayerUtils.js @@ -0,0 +1,312 @@ +/** +* @module LayerUtils +* @alias Gp.LayerUtils +* @description +* ... +* +* @example +* getZoomLevelFromScaleDenominator(); +* getAttributions(); +* intersects(); +*/ +var LayerUtils = { + + /** + * Obtenir le ZoomLevel à partir du ScaleDenominator + * @param {Number} scaleDenominator - the scale denominator + * @param {String} crs - the crs + * + * @returns {Integer} zoom level + */ + getZoomLevelFromScaleDenominator : function (scaleDenominator, crs) { + // ------------------------------------------------- // + // Code issu de l'API Geoportal/Catalogue/Config.js // + // ------------------------------------------------- // + // var configuration = Gp.Config; + // var general = configuration.generalOptions; + // var layers = configuration.layersContext; + // + // for (var tms in general.tileMatrixSets) { + // var tileMatrixSet = general.tileMatrixSets[tms]; + // // IGN's WMTS bug : epsg:nnnn instead of EPSG:nnnn + // var crs = tileMatrixSet.supportedCRS = tileMatrixSet.supportedCRS.replace(/epsg/,"EPSG"); + // + // if (!Geoportal.Catalogue.CRSRESOLUTIONS.hasOwnProperty(crs)) { + // var p= new OpenLayers.Projection(crs); + // Geoportal.Catalogue.CRSRESOLUTIONS[crs]= []; + // var matrixIds= tileMatrixSet.matrixIds; + // for (var i= 0, li= matrixIds.length; i} params.extent - map current geographical extent (EPSG:4326) : [top, left, bottom, right] = [maxy, minx, miny, maxx] + * @param {Number} params.zoom - map current zoom + * @param {String} params.crs - map current projection code (ex "EPSG:2154") + * @param {Boolean} params.visibility - layer visibility + * @param {Gp.Services.Config.Originator} params.originators - resource originators (from Gp.Config.layers[].originators) + * @returns {Object} attributions - associative array, mapping originators url (keys) with their properties : html attributions elements + */ + getAttributions : function (params) { + var zoom = params.zoom; + + var attributions = []; + + if (params.originators != null && params.visibility) { + // drawLogo = boolean, true if attribution should be displayed (zoom, extent), false otherwise + var drawLogo; + for (var j = 0, jl = params.originators.length; j < jl; j++) { + drawLogo = true; + var originator = params.originators[j]; + + var constraints = params.originators[j].constraints || []; + for (var k = 0, kl = constraints.length; k < kl; k++) { + var constraint = constraints[k]; + drawLogo = true; + + var minZoomLevel = this.getZoomLevelFromScaleDenominator(constraint.maxScaleDenominator, params.crs); + var maxZoomLevel = this.getZoomLevelFromScaleDenominator(constraint.minScaleDenominator, params.crs) || 21; + + // min zoom constraints + if (minZoomLevel && (minZoomLevel > zoom)) { + drawLogo = false; + } + + // max zoom constraints + if (drawLogo && maxZoomLevel !== null && (maxZoomLevel < zoom)) { + drawLogo = false; + } + + // bbox constraints + var bbox = constraint.bbox; + if (drawLogo && bbox) { + drawLogo = false; + var viewExtent = params.extent; + if (viewExtent) { + var bounds = [bbox.top, bbox.left, bbox.bottom, bbox.right]; + if (this.intersects(viewExtent, bounds)) { + // at least one constraint matches the map ones + drawLogo = true; + break; + } + } + } + } + + if (drawLogo) { + // on a un originator qui correspond au zoom et à l'étendue. + + var logo = originator.logo; + var url = originator.url; + var name = originator.name ? originator.name : ""; + var text = originator.attribution; + + var container = document.createElement("div"); + container.className = "gp-control-attribution"; + + // on crée un lien dans tous les cas (même s'il ne pointe pas vers une référence), pour avoir accès à la class CSS (pour surcharge) + var link = null; + link = document.createElement("a"); + link.className = "gp-control-attribution-link"; + link.target = "_blank"; + container.appendChild(link); + if (url) { + link.href = url; + } + + var bImage = !!(logo); + var image = null; + // si on a un logo, on l'affiche à l'interieur du lien + if (bImage) { + image = document.createElement("img"); + if (link) { + image.className = "gp-control-attribution-image"; + link.appendChild(image); + } else { + image.className = ""; + container.appendChild(image); + } + image.src = logo; // FIXME : mixContent ! + image.title = text || name; + image.style.height = "30px"; + image.style.width = "30px"; + } else { + // sinon, on affiche le nom de l'originator, ou sa description ou l'url. + if (name) { + link.textContent = name; + } else if (text) { + link.textContent = text; + } else if (url) { + link.textContent = url; + } else { + link.textContent = ""; + } + } + + attributions.push(container.innerHTML + " "); + } + } + } + + return attributions; + }, + + /** + * Determines if one extent (extent1) intersects another (extent2) + * + * @param {Array.} extent1 - First extent : [top, left, bottom, right] = [maxy, minx, miny, maxx] + * @param {Array.} extent2 - Second extent : [top, left, bottom, right] = [maxy, minx, miny, maxx] + * @return {Boolean} intersects - True if the two extents intersect, false otherwise. + */ + intersects : function (extent1, extent2) { + var intersectsX = (extent1[1] <= extent2[3]) && (extent2[1] <= extent1[3]); + var intersectsY = (extent1[2] <= extent2[0]) && (extent2[2] <= extent1[0]); + return intersectsX && intersectsY; + } +}; + +export default LayerUtils; diff --git a/src/Common-review/Utils/LoggerByDefault.js b/src/Common-review/Utils/LoggerByDefault.js new file mode 100644 index 000000000..d6c973443 --- /dev/null +++ b/src/Common-review/Utils/LoggerByDefault.js @@ -0,0 +1,21 @@ +import * as Log from "loglevel"; + +var LoggerByDefault = { + /** + *logger statique + * @param {String} [name="default"] - the logger name + * + * @returns {Object} logger + */ + getLogger : function (name) { + // Substitute global constants configured at compile time + // cf. webpack.config.js + // on masque cette constante afin d'eviter "referenceerror not defined" + ("__PRODUCTION__".match(/true/)) + ? Log.disableAll() : Log.enableAll(); + var logname = name || "default"; + return Log.getLogger(logname); + } +}; + +export default LoggerByDefault; diff --git a/src/Common-review/Utils/MathUtils.js b/src/Common-review/Utils/MathUtils.js new file mode 100644 index 000000000..8b5f7b648 --- /dev/null +++ b/src/Common-review/Utils/MathUtils.js @@ -0,0 +1,111 @@ +/** +* @module MathUtils +* @alias Gp.MathUtils +* @description +* ... +* +* @example +* modulo(); +* decimalToDMS(); +* toInteger(); +* isInteger(); +* toFloat(); +*/ +var MathUtils = { + /** + * Reste de la division euclidienne + * @param {Number} a - divisor + * @param {Number} b - quotient + * @returns {Number} Modulo + */ + modulo : function (a, b) { + var r = a % b; + return r * b < 0 ? r + b : r; + }, + + /** + * Transform degrees, minutes, seconds form decimal degrees - + * Largely inspired by the private function degreesToStringHDMS from ol/coordinate.js + * + * @param {Number} degrees - decimal degrees + * @param {Array} hemispheres - "NS" ou "EO" + * @param {Number} numDigits - number of digits for seconds + * @returns {Object} DMS coordinate + */ + decimalToDMS : function (degrees, hemispheres, numDigits) { + var normalizedDegrees = this.modulo(degrees + 180, 360) - 180; + var x = Math.abs(3600 * normalizedDegrees); + var dflPrecision = numDigits || 0; + var precision = Math.pow(10, dflPrecision); + + var deg = Math.floor(x / 3600); + var min = Math.floor((x - deg * 3600) / 60); + var sec = x - (deg * 3600) - (min * 60); + sec = Math.ceil(sec * precision) / precision; + + if (sec >= 60) { + sec = 0; + min += 1; + } + + if (min >= 60) { + min = 0; + deg += 1; + } + + var direction = hemispheres.charAt(normalizedDegrees < 0 ? 1 : 0); + return { + d : deg, + m : min, + s : sec, + direction : direction + }; + }, + + /** + * Converts string to Integer + * + * @param {String} s - string number + * @param {Numeric} base - between 2 and 36 + * @returns {null|Numeric} result + */ + toInteger : function (s, base) { + var _base = base || 10; + var n = parseInt(s, _base); + if (!isNaN(n) && isFinite(n)) { + return n; + } + return null; + }, + + /** + * check if s represents an integer + * + * @param {String} s - string number + * @returns {Boolean} is integer + */ + isInteger : function (s) { + if (isNaN(s)) { + return false; + } + + var v = parseFloat(s); + return ((v | 0) === v); + }, + + /** + * Converts s to float + * + * @param {String} s - string number + * @returns {null|Numeric} result + */ + toFloat : function (s) { + var n = parseFloat(s); + if (!isNaN(n) && isFinite(n)) { + return n; + } + return null; + } +}; + +export default MathUtils; diff --git a/src/Common-review/Utils/ProxyUtils.js b/src/Common-review/Utils/ProxyUtils.js new file mode 100644 index 000000000..ca9acda12 --- /dev/null +++ b/src/Common-review/Utils/ProxyUtils.js @@ -0,0 +1,50 @@ +import Logger from "../../Common/Utils/LoggerByDefault"; + +/** +* @module ProxyUtils +* @alias Gp.ProxyUtils +* @description +* ... +* +* @example +* proxifyUrl(); +*/ +var ProxyUtils = { + /** + * Ajoute un proxy aux url des couches vecteurs si besoin. + * + * @param {String} url - Url to proxify. + * @param {Object} [proxyOptions] - Object defining proxy options. + * @param {String} proxyOptions.proxyUrl - Proxy URL. + * @param {Array.} [proxyOptions.noProxyDomains] - Proxy will not be used for this list of domain names. + * + * @returns {String} proxy url + */ + proxifyUrl : function (url, proxyOptions) { + // logger + + var logger = Logger.getLogger("proxifyUrl"); + + if (!proxyOptions || + !proxyOptions.hasOwnProperty("proxyUrl") || + proxyOptions.proxyUrl === null || + proxyOptions.proxyUrl.trim().length === 0) { + return url; + } + // on regarde si l'url nest pas dans les domaines sans proxy + if (proxyOptions.noProxyDomains && + Array.isArray(proxyOptions.noProxyDomains) && + proxyOptions.noProxyDomains.length > 0) { + for (var i in proxyOptions.noProxyDomains) { + logger.trace("[ProxyUtils] proxifyUrl : analyzing " + proxyOptions.noProxyDomains[i]); + if (url.indexOf(proxyOptions.noProxyDomains[i]) !== -1) { + logger.info("[ProxyUtils] proxifyUrl : " + url + " found in noProxyDomains list (" + proxyOptions.noProxyDomains[i] + ")."); + return url; + } + } + } + return proxyOptions.proxyUrl + encodeURIComponent(url); + } +}; + +export default ProxyUtils; diff --git a/src/Common-review/Utils/Register.js b/src/Common-review/Utils/Register.js new file mode 100644 index 000000000..bd4e6f510 --- /dev/null +++ b/src/Common-review/Utils/Register.js @@ -0,0 +1,643 @@ +// FIXME +// - exception lors du register IGNF des projections geocent ? +// Ex. Transforming EPSG:4978 geocent projection fails? +// cf. https://github.com/proj4js/proj4js/issues/195 +// - probleme de performance avec le chargement des projections (env. 4s), +// et ceci bloque le rendu graphique... + +/** + * Register definition for IGNF, and EPSG CRS. + * @example + * Gp.Register.IGNF.AMST63 + * // return : "+title=Amsterdam 1963 +proj=geocent +towgs84=109.753,-528.133,-362.244,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs" + * Gp.Register.get("IGNF:AMST63") + * // same as Gp.Register.IGNF.AMST63 + */ +var Register = { + + /** + * instance already loaded into proj4 + */ + isLoaded : false, + + /** + * get the definition for a code + * + * @param {String} name - ie. EPSG:2154 (Lambert) + * @returns {Object} definition + * @example + * Register.get("EPSG:2154"); + * // "+title=RGF93 / Lambert-93 +proj=lcc +lat_1=49 ..." + */ + get : function (name) { + if (name === "" || name === null || typeof name === "undefined") { + return; + } + + var s = name.split(":"); + if (s.length !== 2) { + return; + } + + var _register = s[0]; + var _code = s[1]; + + if (!this.hasOwnProperty(_register)) { + return; + } + + if (!this[_register].hasOwnProperty(_code)) { + return; + } + + return this[_register][_code]; + }, + + /** + * does projection code exist ? + * + * @param {String} name - ie. EPSG:2154 (Lambert) + * @returns {Boolean} true/false + * @example + * Register.exist("EPSG:2154"); // true + */ + exist : function (name) { + if (name === "" || name === null || typeof name === "undefined") { + return false; + } + + var s = name.split(":"); + if (s.length !== 2) { + return false; + } + + var _register = s[0]; + var _code = s[1]; + + if (!this.hasOwnProperty(_register)) { + return false; + } + + if (!this[_register].hasOwnProperty(_code)) { + return false; + } + + return true; + }, + + /** + * load all defs to proj4 + * @param {Object} Proj4 - proj4 instance + */ + load : function (Proj4) { + // un flag pour savoir si le chargement est déjà realisé + // (car ceci peut être couteux !) + if (!this.isLoaded) { + var registers = [ + "IGNF", // exception lors du register IGNF ? + "EPSG", + "CRS" + ]; + for (var i = 0; i < registers.length; i++) { + var _register = registers[i]; + var codes = this[_register]; + for (var _code in codes) { + if (codes.hasOwnProperty(_code)) { + var name = _register + ":" + _code; + Proj4.defs(name, this.get(name)); + // on enlève la dependance à OpenLayers... + // la fonction register est donc à appeller afin d'enregistrer + // les definitions dans OpenLayers : + // import { get } from "ol/proj"; + // import proj4 from "proj4"; + // import { register } from "ol/proj/proj4"; + // Register.load(); + // // Make projections defined in proj4 (with proj4.defs()) available in OpenLayers. + // // see ol/proj/proj4.register (https://openlayers.org/en/latest/apidoc/module-ol_proj_proj4.html) + // register(proj4); + // console.log(get("CRS:84").getCode()); // "CRS:84" + } + } + } + this.isLoaded = true; + } + }, + + /** + * load defs by default to proj4 + * + * include into proj4 : + * - WGS84 + * - ['EPSG:4326'] + * - ['EPSG:3785'], ['EPSG:3857'], GOOGLE, ['EPSG:900913'], ['EPSG:102113'] + * + + * - ["EPSG:2154"], ["EPSG:27571"], ["EPSG:27572"], ["EPSG:27573"], ["EPSG:2757"], + * - ["CRS:84"], + * - ["IGNF:LAMB93"], + * - ["IGNF:LAMBE"], ["IGNF:LAMB1"], ["IGNF:LAMB2"], ["IGNF:LAMB3"], ["IGNF:LAMB4"], + * - ["IGNF:RGF93G"], + * - ["IGNF:WGS84G"] + * + * @param {Object} Proj4 - proj4 instance + */ + loadByDefault : function (Proj4) { + // FIXME definir la liste de projections par defaut... + var registers = { + EPSG : { + 2154 : Register["EPSG"]["2154"], + 27571 : Register["EPSG"]["27571"], + 27572 : Register["EPSG"]["27572"], + 27573 : Register["EPSG"]["27573"], + 27574 : Register["EPSG"]["27574"] + }, + CRS : { + 84 : Register["CRS"]["84"] + }, + IGNF : { + LAMB93 : Register["IGNF"]["LAMB93"], + LAMBE : Register["IGNF"]["LAMBE"], + LAMB1 : Register["IGNF"]["LAMB1"], + LAMB2 : Register["IGNF"]["LAMB2"], + LAMB3 : Register["IGNF"]["LAMB3"], + LAMB4 : Register["IGNF"]["LAMB4"], + RGF93G : Register["IGNF"]["RGF93G"], + WGS84G : Register["IGNF"]["WGS84G"] + } + }; + + for (var register in registers) { + if (registers.hasOwnProperty(register)) { + var codes = registers[register]; + for (var code in codes) { + if (codes.hasOwnProperty(code)) { + var name = register + ":" + code; + Proj4.defs(name, codes[code]); + } + } + } + } + }, + + /** + * load only a def to proj4 + * @param {Object} Proj4 - proj4 instance + * @param {String} name - ie. EPSG:2154 (Lambert) + * @returns {Boolean} true/false + */ + loadByName : function (Proj4, name) { + if (!this.exist(name)) { + return false; + } + + try { + Proj4.defs(name, this.get(name)); + } catch (e) { + // FIXME !? + return false; + } + + return true; + }, + + // definitions + EPSG : { + // 4978 : "+proj=geocent +datum=WGS84 +units=m +no_defs ", + 3857 : "+title=WGS 84 / Pseudo-Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs", + 3785 : "+title=WGS 84 / Pseudo-Mercator (deprecated) +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs", + 4149 : "+title=CH1903 +proj=longlat +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +no_defs ", + 4150 : "+title=CH1903plus +proj=longlat +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +no_defs ", + 4151 : "+title=CHTRF95 +proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs ", + 4171 : "+title=RGF93 +proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs ", + 4230 : "+title=ED50 +proj=longlat +ellps=intl +no_defs ", + 4235 : "+title=Guyane Francaise +proj=longlat +ellps=intl +no_defs ", + 4258 : "+title=ETRS89 +proj=longlat +ellps=GRS80 +no_defs ", + 4275 : "+title=NTF +proj=longlat +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +no_defs ", + 4322 : "+title=WGS 72 +proj=longlat +ellps=WGS72 +no_defs ", + 4326 : "+title=WGS 84 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ", + 4467 : "+proj=utm +zone=21 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 4470 : "+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs ", + 4471 : "+proj=utm +zone=38 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 4474 : "+proj=utm +zone=38 +south +ellps=intl +towgs84=-382,-59,-262,0,0,0,0 +units=m +no_defs ", + 4558 : "+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs ", + 4559 : "+proj=utm +zone=20 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 4621 : "+title=Fort Marigot +proj=longlat +ellps=intl +towgs84=137,248,-430,0,0,0,0 +no_defs ", + 4622 : "+title=Guadeloupe 1948 +proj=longlat +ellps=intl +no_defs ", + 4623 : "+title=CSG67 +proj=longlat +ellps=intl +towgs84=-186,230,110,0,0,0,0 +no_defs ", + 4624 : "+title=RGFG95 +proj=longlat +ellps=GRS80 +towgs84=2,2,-2,0,0,0,0 +no_defs ", + 4625 : "+title=Martinique 1938 +proj=longlat +ellps=intl +no_defs ", + 4626 : "+title=Reunion 1947 +proj=longlat +ellps=intl +no_defs ", + 4627 : "+title=RGR92 +proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs ", + 4628 : "+title=Tahiti 52 +proj=longlat +ellps=intl +towgs84=162,117,154,0,0,0,0 +no_defs ", + 4629 : "+title=Tahaa 54 +proj=longlat +ellps=intl +no_defs ", + 4630 : "+title=IGN72 Nuku Hiva +proj=longlat +ellps=intl +no_defs ", + 4632 : "+title=Combani 1950 +proj=longlat +ellps=intl +towgs84=-382,-59,-262,0,0,0,0 +no_defs ", + 4633 : "+title=IGN56 Lifou +proj=longlat +ellps=intl +no_defs ", + 4634 : "+title=IGN72 Grand Terre +proj=longlat +ellps=intl +no_defs ", + 4637 : "+title=Perroud 1950 +proj=longlat +ellps=intl +towgs84=325,154,172,0,0,0,0 +no_defs ", + 4638 : "+title=Saint Pierre et Miquelon 1950 +proj=longlat +ellps=clrk66 +towgs84=30,430,368,0,0,0,0 +no_defs ", + 4640 : "+title=RRAF 1991 +proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs ", + 4641 : "+title=IGN53 Mare +proj=longlat +ellps=intl +no_defs ", + 4645 : "+title=RGNC 1991 +proj=longlat +ellps=intl +towgs84=0,0,0,0,0,0,0 +no_defs ", + 4687 : "+proj=longlat +ellps=GRS80 +no_defs ", + 4662 : "+title=IGN72 Grande Terre +proj=longlat +ellps=intl +no_defs ", + 4689 : "+title=IGN63 Hiva Oa +proj=longlat +ellps=intl +no_defs ", + 4690 : "+title=Tahiti 79 +proj=longlat +ellps=intl +no_defs ", + 4691 : "+title=Moorea 87 +proj=longlat +ellps=intl +towgs84=215.525,149.593,176.229,-3.2624,-1.692,-1.1571,10.4773 +no_defs ", + 4692 : "+title=Maupiti 83 +proj=longlat +ellps=intl +towgs84=217.037,86.959,23.956,0,0,0,0 +no_defs ", + 4698 : "+title=IGN 1962 Kerguelen +proj=longlat +ellps=intl +towgs84=145,-187,103,0,0,0,0 +no_defs ", + 4749 : "+title=RGNC91-93 +proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs ", + 4750 : "+title=ST87 Ouvea +proj=longlat +ellps=WGS84 +towgs84=-56.263,16.136,-22.856,0,0,0,0 +no_defs ", + 4807 : "+title=NTF (Paris) +proj=longlat +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +no_defs ", + 2056 : "+title=CH1903+ / LV95 +proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs ", + 2154 : "+title=RGF93 / Lambert-93 +proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 2213 : "+title=ETRS89 / TM 30 NE +proj=tmerc +lat_0=0 +lon_0=30 +k=0.9996 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs ", + 2969 : "+title=Fort Marigot / UTM zone 20N +proj=utm +zone=20 +ellps=intl +towgs84=137,248,-430,0,0,0,0 +units=m +no_defs ", + 2970 : "+title=Guadeloupe 1948 / UTM zone 20N +proj=utm +zone=20 +ellps=intl +units=m +no_defs ", + 2971 : "+title=CSG67 / UTM zone 22N +proj=utm +zone=22 +ellps=intl +towgs84=-186,230,110,0,0,0,0 +units=m +no_defs ", + 2972 : "+title=RGFG95 / UTM zone 22N +proj=utm +zone=22 +ellps=GRS80 +towgs84=2,2,-2,0,0,0,0 +units=m +no_defs ", + 2973 : "+title=Martinique 1938 / UTM zone 20N +proj=utm +zone=20 +ellps=intl +units=m +no_defs ", + 2975 : "+title=RGR92 / UTM zone 40S +proj=utm +zone=40 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 2976 : "+title=Tahiti 52 / UTM zone 6S +proj=utm +zone=6 +south +ellps=intl +towgs84=162,117,154,0,0,0,0 +units=m +no_defs ", + 2977 : "+title=Tahaa 54 / UTM zone 5S +proj=utm +zone=5 +south +ellps=intl +units=m +no_defs ", + 2978 : "+title=IGN72 Nuku Hiva / UTM zone 7S +proj=utm +zone=7 +south +ellps=intl +units=m +no_defs ", + 2980 : "+title=Combani 1950 / UTM zone 38S +proj=utm +zone=38 +south +ellps=intl +towgs84=-382,-59,-262,0,0,0,0 +units=m +no_defs ", + 2981 : "+title=IGN56 Lifou / UTM zone 58S +proj=utm +zone=58 +south +ellps=intl +units=m +no_defs ", + 2982 : "+title=IGN72 Grand Terre / UTM zone 58S (deprecated) +proj=utm +zone=58 +south +ellps=intl +units=m +no_defs ", + 2984 : "+title=RGNC 1991 / Lambert New Caledonia (deprecated) +proj=lcc +lat_1=-20.66666666666667 +lat_2=-22.33333333333333 +lat_0=-21.5 +lon_0=166 +x_0=400000 +y_0=300000 +ellps=intl +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 2986 : "+title=Terre Adelie 1950 +proj=stere +towgs84=324.9120,153.2820,172.0260 +a=6378388.0000 +rf=297.0000000000000 +lat_0=-90.000000000 +lon_0=140.000000000 +lat_ts=-67.000000000 +k=0.96027295 +x_0=300000.000 +y_0=-2299363.482 +units=m +no_defs", + 2987 : "+title=Saint Pierre et Miquelon 1950 / UTM zone 21N +proj=utm +zone=21 +ellps=clrk66 +towgs84=30,430,368,0,0,0,0 +units=m +no_defs ", + 2989 : "+title=RRAF 1991 / UTM zone 20N +proj=utm +zone=20 +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 2990 : "+title=Reunion 1947 / TM Reunion (deprecated) +proj=tmerc +lat_0=-21.11666666666667 +lon_0=55.53333333333333 +k=1 +x_0=50000 +y_0=160000 +ellps=intl +units=m +no_defs ", + 2995 : "+title=IGN53 Mare / UTM zone 58S +proj=utm +zone=58 +south +ellps=intl +units=m +no_defs ", + 3038 : "+proj=utm +zone=26 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3039 : "+proj=utm +zone=27 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3040 : "+proj=utm +zone=28 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3041 : "+proj=utm +zone=29 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + // 3042 : "+proj=utm +zone=30 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + // 3043 : "+proj=utm +zone=31 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + // 3044 : "+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3045 : "+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3046 : "+proj=utm +zone=34 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3047 : "+proj=utm +zone=35 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3048 : "+proj=utm +zone=36 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3049 : "+proj=utm +zone=37 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3050 : "+proj=utm +zone=38 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3051 : "+proj=utm +zone=39 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3034 : "+title=ETRS89 / ETRS-LCC +proj=lcc +lat_1=35 +lat_2=65 +lat_0=52 +lon_0=10 +x_0=4000000 +y_0=2800000 +ellps=GRS80 +units=m +no_defs ", + 3035 : "+title=ETRS89 / ETRS-LAEA +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs ", + 3042 : "+title=ETRS89 / ETRS-TM30 +proj=utm +zone=30 +ellps=GRS80 +units=m +no_defs ", + 3043 : "+title=ETRS89 / ETRS-TM31 +proj=utm +zone=31 +ellps=GRS80 +units=m +no_defs ", + 3044 : "+title=ETRS89 / ETRS-TM32 +proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs ", + 25828 : "+proj=utm +zone=28 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 25829 : "+proj=utm +zone=29 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + // 25830 : "+proj=utm +zone=30 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + // 25831 : "+proj=utm +zone=31 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + // 25832 : "+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 25833 : "+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 25834 : "+proj=utm +zone=34 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 25835 : "+proj=utm +zone=35 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 25836 : "+proj=utm +zone=36 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 25837 : "+proj=utm +zone=37 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 25838 : "+proj=utm +zone=38 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3060 : "+title=IGN72 Grande Terre / UTM zone 58S +proj=utm +zone=58 +south +ellps=intl +units=m +no_defs ", + 3163 : "+title=RGNC91-93 / Lambert New Caledonia +proj=lcc +lat_1=-20.66666666666667 +lat_2=-22.33333333333333 +lat_0=-21.5 +lon_0=166 +x_0=400000 +y_0=300000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3164 : "+title=ST87 Ouvea / UTM zone 58S +proj=utm +zone=58 +south +ellps=WGS84 +towgs84=-56.263,16.136,-22.856,0,0,0,0 +units=m +no_defs ", + 3165 : "+title=NEA74 Noumea / Noumea Lambert +proj=lcc +lat_1=-22.24469175 +lat_2=-22.29469175 +lat_0=-22.26969175 +lon_0=166.44242575 +x_0=0.66 +y_0=1.02 +ellps=intl +units=m +no_defs ", + 3166 : "+title=NEA74 Noumea / Noumea Lambert 2 +proj=lcc +lat_1=-22.24472222222222 +lat_2=-22.29472222222222 +lat_0=-22.26972222222222 +lon_0=166.4425 +x_0=8.313000000000001 +y_0=-2.354 +ellps=intl +units=m +no_defs ", + 3169 : "+title=RGNC91-93 / UTM zone 57S +proj=utm +zone=57 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3170 : "+title=RGNC91-93 / UTM zone 58S +proj=utm +zone=58 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3171 : "+title=RGNC91-93 / UTM zone 59S +proj=utm +zone=59 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ", + 3172 : "+title=IGN53 Mare / UTM zone 59S +proj=utm +zone=59 +south +ellps=intl +units=m +no_defs ", + 3296 : "+title=RGPF / UTM zone 5S +proj=utm +zone=5 +south +ellps=GRS80 +units=m +no_defs ", + 3297 : "+title=RGPF / UTM zone 6S +proj=utm +zone=6 +south +ellps=GRS80 +units=m +no_defs ", + 3298 : "+title=RGPF / UTM zone 7S +proj=utm +zone=7 +south +ellps=GRS80 +units=m +no_defs ", + 3299 : "+title=RGPF / UTM zone 8S +proj=utm +zone=8 +south +ellps=GRS80 +units=m +no_defs ", + 3302 : "+title=IGN63 Hiva Oa / UTM zone 7S +proj=utm +zone=7 +south +ellps=intl +units=m +no_defs ", + 3303 : "+title=Fatu Iva 72 / UTM zone 7S +proj=utm +zone=7 +south +ellps=intl +towgs84=347.103,1078.12,2623.92,-33.8875,70.6773,-9.3943,186.074 +units=m +no_defs ", + 3304 : "+title=Tahiti 79 / UTM zone 6S +proj=utm +zone=6 +south +ellps=intl +units=m +no_defs ", + 3305 : "+title=Moorea 87 / UTM zone 6S +proj=utm +zone=6 +south +ellps=intl +towgs84=215.525,149.593,176.229,-3.2624,-1.692,-1.1571,10.4773 +units=m +no_defs ", + 3306 : "+title=Maupiti 83 / UTM zone 5S +proj=utm +zone=5 +south +ellps=intl +towgs84=217.037,86.959,23.956,0,0,0,0 +units=m +no_defs ", + 3312 : "+title=CSG67 / UTM zone 21N +proj=utm +zone=21 +ellps=intl +towgs84=-186,230,110,0,0,0,0 +units=m +no_defs ", + 3313 : "+title=RGFG95 / UTM zone 21N +proj=utm +zone=21 +ellps=GRS80 +towgs84=2,2,-2,0,0,0,0 +units=m +no_defs ", + 3336 : "+title=IGN 1962 Kerguelen / UTM zone 42S +proj=utm +zone=42 +south +ellps=intl +towgs84=145,-187,103,0,0,0,0 +units=m +no_defs ", + 3395 : "+title=WGS 84 / World Mercator +proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 3727 : "+title=Reunion 1947 / TM Reunion +proj=tmerc +lat_0=-21.11666666666667 +lon_0=55.53333333333333 +k=1 +x_0=160000 +y_0=50000 +ellps=intl +units=m +no_defs ", + 21781 : "+title=CH1903 / LV03 +proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +x_0=600000 +y_0=200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs ", + 25830 : "+title=ETRS89 / UTM zone 30N +proj=utm +zone=30 +ellps=GRS80 +units=m +no_defs ", + 25831 : "+title=ETRS89 / UTM zone 31N +proj=utm +zone=31 +ellps=GRS80 +units=m +no_defs ", + 25832 : "+title=ETRS89 / UTM zone 32N +proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs ", + 27561 : "+title=NTF (Paris) / Lambert Nord France +proj=lcc +lat_1=49.50000000000001 +lat_0=49.50000000000001 +lon_0=0 +k_0=0.999877341 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27562 : "+title=NTF (Paris) / Lambert Centre France +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27563 : "+title=NTF (Paris) / Lambert Sud France +proj=lcc +lat_1=44.10000000000001 +lat_0=44.10000000000001 +lon_0=0 +k_0=0.9998774990000001 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27564 : "+title=NTF (Paris) / Lambert Corse +proj=lcc +lat_1=42.16500000000001 +lat_0=42.16500000000001 +lon_0=0 +k_0=0.9999447100000001 +x_0=234.358 +y_0=185861.369 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27571 : "+title=NTF (Paris) / Lambert zone I +proj=lcc +lat_1=49.50000000000001 +lat_0=49.50000000000001 +lon_0=0 +k_0=0.999877341 +x_0=600000 +y_0=1200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27572 : "+title=NTF (Paris) / Lambert zone II +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27573 : "+title=NTF (Paris) / Lambert zone III +proj=lcc +lat_1=44.10000000000001 +lat_0=44.10000000000001 +lon_0=0 +k_0=0.9998774990000001 +x_0=600000 +y_0=3200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27574 : "+title=NTF (Paris) / Lambert zone IV +proj=lcc +lat_1=42.16500000000001 +lat_0=42.16500000000001 +lon_0=0 +k_0=0.9999447100000001 +x_0=234.358 +y_0=4185861.369 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27581 : "+title=NTF (Paris) / France I (deprecated) +proj=lcc +lat_1=49.50000000000001 +lat_0=49.50000000000001 +lon_0=0 +k_0=0.999877341 +x_0=600000 +y_0=1200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27582 : "+title=NTF (Paris) / France II (deprecated) +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27583 : "+title=NTF (Paris) / France III (deprecated) +proj=lcc +lat_1=44.10000000000001 +lat_0=44.10000000000001 +lon_0=0 +k_0=0.9998774990000001 +x_0=600000 +y_0=3200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27584 : "+title=NTF (Paris) / France IV (deprecated) +proj=lcc +lat_1=42.16500000000001 +lat_0=42.16500000000001 +lon_0=0 +k_0=0.9999447100000001 +x_0=234.358 +y_0=4185861.369 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27591 : "+title=NTF (Paris) / Nord France (deprecated) +proj=lcc +lat_1=49.50000000000001 +lat_0=49.50000000000001 +lon_0=0 +k_0=0.999877341 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27592 : "+title=NTF (Paris) / Centre France (deprecated) +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27593 : "+title=NTF (Paris) / Sud France (deprecated) +proj=lcc +lat_1=44.10000000000001 +lat_0=44.10000000000001 +lon_0=0 +k_0=0.9998774990000001 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 27594 : "+title=NTF (Paris) / Corse (deprecated) +proj=lcc +lat_1=42.16500000000001 +lat_0=42.16500000000001 +lon_0=0 +k_0=0.9999447100000001 +x_0=234.358 +y_0=185861.369 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ", + 32601 : "+proj=utm +zone=1 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32602 : "+proj=utm +zone=2 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32603 : "+proj=utm +zone=3 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32604 : "+proj=utm +zone=4 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32605 : "+proj=utm +zone=5 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32606 : "+proj=utm +zone=6 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32607 : "+proj=utm +zone=7 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32608 : "+proj=utm +zone=8 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32609 : "+proj=utm +zone=9 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32610 : "+proj=utm +zone=10 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32611 : "+proj=utm +zone=11 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32612 : "+proj=utm +zone=12 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32613 : "+proj=utm +zone=13 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32614 : "+proj=utm +zone=14 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32615 : "+proj=utm +zone=15 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32616 : "+proj=utm +zone=16 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32617 : "+proj=utm +zone=17 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32618 : "+proj=utm +zone=18 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32619 : "+proj=utm +zone=19 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32620 : "+proj=utm +zone=20 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32621 : "+proj=utm +zone=21 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32622 : "+proj=utm +zone=22 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32623 : "+proj=utm +zone=23 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32624 : "+proj=utm +zone=24 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32625 : "+proj=utm +zone=25 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32626 : "+proj=utm +zone=26 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32627 : "+proj=utm +zone=27 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32628 : "+proj=utm +zone=28 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32629 : "+proj=utm +zone=29 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32630 : "+proj=utm +zone=30 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32631 : "+proj=utm +zone=31 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32632 : "+proj=utm +zone=32 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32633 : "+proj=utm +zone=33 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32634 : "+proj=utm +zone=34 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32635 : "+proj=utm +zone=35 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32636 : "+proj=utm +zone=36 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32637 : "+proj=utm +zone=37 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32638 : "+proj=utm +zone=38 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32639 : "+proj=utm +zone=39 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32640 : "+proj=utm +zone=40 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32641 : "+proj=utm +zone=41 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32642 : "+proj=utm +zone=42 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32643 : "+proj=utm +zone=43 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32644 : "+proj=utm +zone=44 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32645 : "+proj=utm +zone=45 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32646 : "+proj=utm +zone=46 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32647 : "+proj=utm +zone=47 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32648 : "+proj=utm +zone=48 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32649 : "+proj=utm +zone=49 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32650 : "+proj=utm +zone=50 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32651 : "+proj=utm +zone=51 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32652 : "+proj=utm +zone=52 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32653 : "+proj=utm +zone=53 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32654 : "+proj=utm +zone=54 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32655 : "+proj=utm +zone=55 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32656 : "+proj=utm +zone=56 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32657 : "+proj=utm +zone=57 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32658 : "+proj=utm +zone=58 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32659 : "+proj=utm +zone=59 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32660 : "+proj=utm +zone=60 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32661 : "+proj=stere +lat_0=90 +lat_ts=90 +lon_0=0 +k=0.994 +x_0=2000000 +y_0=2000000 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32662 : "+title=WGS 84 / Plate Carree +proj=eqc +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32701 : "+proj=utm +zone=1 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32702 : "+proj=utm +zone=2 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32703 : "+proj=utm +zone=3 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32704 : "+proj=utm +zone=4 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32705 : "+proj=utm +zone=5 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32706 : "+proj=utm +zone=6 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32707 : "+proj=utm +zone=7 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32708 : "+proj=utm +zone=8 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32709 : "+proj=utm +zone=9 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32710 : "+proj=utm +zone=10 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32711 : "+proj=utm +zone=11 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32712 : "+proj=utm +zone=12 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32713 : "+proj=utm +zone=13 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32714 : "+proj=utm +zone=14 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32715 : "+proj=utm +zone=15 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32716 : "+proj=utm +zone=16 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32717 : "+proj=utm +zone=17 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32718 : "+proj=utm +zone=18 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32719 : "+proj=utm +zone=19 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32720 : "+proj=utm +zone=20 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32721 : "+proj=utm +zone=21 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32722 : "+proj=utm +zone=22 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32723 : "+proj=utm +zone=23 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32724 : "+proj=utm +zone=24 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32725 : "+proj=utm +zone=25 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32726 : "+proj=utm +zone=26 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32727 : "+proj=utm +zone=27 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32728 : "+proj=utm +zone=28 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32729 : "+proj=utm +zone=29 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32730 : "+proj=utm +zone=30 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32731 : "+proj=utm +zone=31 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32732 : "+proj=utm +zone=32 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32733 : "+proj=utm +zone=33 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32734 : "+proj=utm +zone=34 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32735 : "+proj=utm +zone=35 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32736 : "+proj=utm +zone=36 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32737 : "+proj=utm +zone=37 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32738 : "+proj=utm +zone=38 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32739 : "+proj=utm +zone=39 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32740 : "+proj=utm +zone=40 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32741 : "+proj=utm +zone=41 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32742 : "+proj=utm +zone=42 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32743 : "+proj=utm +zone=43 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32744 : "+proj=utm +zone=44 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32745 : "+proj=utm +zone=45 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32746 : "+proj=utm +zone=46 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32747 : "+proj=utm +zone=47 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32748 : "+proj=utm +zone=48 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32749 : "+proj=utm +zone=49 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32750 : "+proj=utm +zone=50 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32751 : "+proj=utm +zone=51 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32752 : "+proj=utm +zone=52 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32753 : "+proj=utm +zone=53 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32754 : "+proj=utm +zone=54 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32755 : "+proj=utm +zone=55 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32756 : "+proj=utm +zone=56 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32757 : "+proj=utm +zone=57 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32758 : "+proj=utm +zone=58 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32759 : "+proj=utm +zone=59 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32760 : "+proj=utm +zone=60 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 32761 : "+proj=stere +lat_0=-90 +lat_ts=-90 +lon_0=0 +k=0.994 +x_0=2000000 +y_0=2000000 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ", + 310024802 : "+title=Geoportail - France metropolitaine +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=46.500000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 310915814 : "+title=Geoportail - Antilles francaises +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=15.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 310486805 : "+title=Geoportail - Guyane +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=4.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 310700806 : "+title=Geoportail - Reunion et dependances +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-21.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 310702807 : "+title=Geoportail - Mayotte +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-12.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 310706808 : "+title=Geoportail - Saint-Pierre et Miquelon +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=47.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 310547809 : "+title=Geoportail - Nouvelle-Caledonie +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-22.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 310642810 : "+title=Geoportail - Wallis et Futuna +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.000000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-14.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 310032811 : "+title=Geoportail - Polynesie francaise +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-15.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 310642812 : "+title=Geoportail - Kerguelen +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-49.500000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 310642801 : "+title=Geoportail - Crozet +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-46.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 310642813 : "+title=Geoportail - Amsterdam et Saint-Paul +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-38.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 310642901 : "+title=Geoportail - Monde +proj=mill +towgs84=0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.000000 +a=6378137.0000 +rf=298.2572221010000 +lon_0=0.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + 5489 : "+title=RGAF09 geographiques (dms) +proj=longlat +nadgrids=@null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137 +rf=298.257222101 +units=m +no_defs", + 5490 : "+title=RGAF09 UTM Nord Fuseau 20 +proj=tmerc +nadgrids=@null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137 +rf=298.257222101 +lat_0=0.000000000 +lon_0=-63.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs" + }, + CRS : { + 84 : "+title=WGS 84 longitude-latitude +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs " + }, + IGNF : { + // AMST63 : "+title=Amsterdam 1963 +proj=geocent +towgs84=109.753,-528.133,-362.244,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // CROZ63 : "+title=Crozet 1963 +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // CSG67 : "+title=Guyane CSG67 +proj=geocent +towgs84=-193.0660,236.9930,105.4470,0.4814,-0.8074,0.1276,1.564900 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // ED50 : "+title=ED50 +proj=geocent +towgs84=-84.0000,-97.0000,-117.0000 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // ETRS89 : "+title=Systeme de reference terrestre Europeen (1989) +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + // GUAD48 : "+title=Guadeloupe Ste Anne +proj=geocent +towgs84=-472.2900,-5.6300,-304.1200,0.4362,-0.8374,0.2563,1.898400 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // GUADFM49 : "+title=Guadeloupe Fort Marigot +proj=geocent +towgs84=136.5960,248.1480,-429.7890 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // IGN63 : "+title=IGN 1963 (Hiva Oa, Tahuata, Mohotani) +proj=geocent +towgs84=410.7210,55.0490,80.7460,-2.5779,-2.3514,-0.6664,17.331100 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // IGN72 : "+title=IGN 1972 Grande-Terre / Ile des Pins +proj=geocent +towgs84=-11.6400,-348.6000,291.6800 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // KERG62CAR : "+title=Kerguelen - K0 +proj=geocent +towgs84=144.8990,-186.7700,100.9230 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // MART38 : "+title=Martinique Fort-Desaix +proj=geocent +towgs84=126.9260,547.9390,130.4090,-2.7867,5.1612,-0.8584,13.822650 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // MAYO50 : "+title=Mayotte Combani +proj=geocent +towgs84=-599.9280,-275.5520,-195.6650,-0.0835,-0.4715,0.0602,49.281400 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // MOOREA87 : "+title=Moorea 1987 +proj=geocent +towgs84=215.9820,149.5930,176.2290,3.2624,1.6920,1.1571,10.477300 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // NTF : "+title=Nouvelle Triangulation Francaise +proj=geocent +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +units=m +no_defs", + // NUKU72 : "+title=IGN 1972 Nuku Hiva +proj=geocent +towgs84=165.7320,216.7200,180.5050,-0.6434,-0.4512,-0.0791,7.420400 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // REUN47 : "+title=Reunion 1947 +proj=geocent +towgs84=789.5240,-626.4860,-89.9040,0.6006,76.7946,-10.5788,-32.324100 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // RGF93 : "+title=Reseau geodesique francais 1993 +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + // RGFG95 : "+title=Reseau geodesique francais de Guyane 1995 +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + // RGM04 : "+title=RGM04 (Reseau Geodesique de Mayotte 2004) +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + // RGNC : "+title=Reseau Geodesique de Nouvelle-Caledonie +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + // RGPF : "+title=RGPF (Reseau Geodesique de Polynesie Francaise) +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + // RGR92 : "+title=Reseau geodesique Reunion 1992 +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + // RGSPM06 : "+title=Reseau Geodesique Saint-Pierre-et-Miquelon (2006) +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + // RGTAAF07 : "+title=Reseau Geodesique des TAAF (2007) +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + // RRAF91 : "+title=RRAF 1991 (Reseau de Reference des Antilles Francaises) +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + // STPL69 : "+title=Saint-Paul 1969 +proj=geocent +towgs84=225.571,-346.608,-46.567,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // STPM50 : "+title=St Pierre et Miquelon 1950 +proj=geocent +towgs84=-95.5930,573.7630,173.4420,-0.9602,1.2510,-1.3918,42.626500 +a=6378206.4000 +rf=294.9786982000000 +units=m +no_defs", + // TAHAA : "+title=Raiatea - Tahaa 51-54 (Tahaa, Base Terme Est) +proj=geocent +towgs84=72.4380,345.9180,79.4860,-1.6045,-0.8823,-0.5565,1.374600 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // TAHI79 : "+title=IGN79 (Tahiti) Iles de la Societe +proj=geocent +towgs84=221.5250,152.9480,176.7680,2.3847,1.3896,0.8770,11.474100 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // TERA50 : "+title=Pointe Geologie - Perroud 1950 +proj=geocent +towgs84=324.9120,153.2820,172.0260 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // WALL78 : "+title=Wallis-Uvea 1978 (MOP78) +proj=geocent +towgs84=253.0000,-133.0000,-127.0000 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + // WGS72 : "+title=World Geodetic System 1972 +proj=geocent +towgs84=0.0000,12.0000,6.0000 +a=6378135.0000 +rf=298.2600000000000 +units=m +no_defs", + // WGS84 : "+title=World Geodetic System 1984 +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + AMST63GEO : "+title=Amsterdam 1963 +proj=longlat +towgs84=109.753,-528.133,-362.244,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + CROZ63GEO : "+title=Crozet 1963 +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + CSG67GEO : "+title=Guyane CSG67 +proj=longlat +towgs84=-193.0660,236.9930,105.4470,0.4814,-0.8074,0.1276,1.564900 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + ED50G : "+title=ED50 +proj=longlat +towgs84=-84.0000,-97.0000,-117.0000 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + GUAD48GEO : "+title=Guadeloupe Ste Anne +proj=longlat +towgs84=-472.2900,-5.6300,-304.1200,0.4362,-0.8374,0.2563,1.898400 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + GUADFM49GEO : "+title=Guadeloupe Fort Marigot +proj=longlat +towgs84=136.5960,248.1480,-429.7890 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + IGN63GEO : "+title=IGN 1963 (Hiva Oa, Tahuata, Mohotani) +proj=longlat +towgs84=410.7210,55.0490,80.7460,-2.5779,-2.3514,-0.6664,17.331100 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + IGN72GEO : "+title=IGN 1972 Grande-Terre / Ile des Pins +proj=longlat +towgs84=-11.6400,-348.6000,291.6800 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + KERG62GEO : "+title=Kerguelen - K0 +proj=longlat +towgs84=144.8990,-186.7700,100.9230 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + MART38GEO : "+title=Martinique Fort-Desaix +proj=longlat +towgs84=126.9260,547.9390,130.4090,-2.7867,5.1612,-0.8584,13.822650 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + MAYO50GEO : "+title=Mayotte Combani +proj=longlat +towgs84=-599.9280,-275.5520,-195.6650,-0.0835,-0.4715,0.0602,49.281400 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + MOOREA87GEO : "+title=Moorea 1987 +proj=longlat +towgs84=215.9820,149.5930,176.2290,3.2624,1.6920,1.1571,10.477300 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + NTFG : "+title=Nouvelle Triangulation Francaise Greenwich degres sexagesimaux +proj=longlat +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +units=m +no_defs", + NTFP : "+title=Nouvelle Triangulation Francaise Paris grades +proj=longlat +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +units=m +no_defs", + NUKU72GEO : "+title=IGN 1972 Nuku Hiva +proj=longlat +towgs84=165.7320,216.7200,180.5050,-0.6434,-0.4512,-0.0791,7.420400 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + REUN47GEO : "+title=Reunion 1947 +proj=longlat +towgs84=789.5240,-626.4860,-89.9040,0.6006,76.7946,-10.5788,-32.324100 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + RGF93G : "+title=Reseau geodesique francais 1993 +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + RGFG95GEO : "+title=Reseau geodesique francais de Guyane 1995 +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + RGM04GEO : "+title=RGM04 (Reseau Geodesique de Mayotte 2004) +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + RGNCGEO : "+title=Reseau Geodesique de Nouvelle-Caledonie +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + RGPFGEO : "+title=RGPF (Reseau Geodesique de Polynesie Francaise) +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + RGR92GEO : "+title=Reseau geodesique de la Reunion 1992 +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + RGSPM06GEO : "+title=Saint-Pierre-et-Miquelon (2006) +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + RGTAAF07G : "+title=Reseau Geodesique des TAAF (2007) (dms) +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + STPL69GEO : "+title=Saint-Paul 1969 +proj=longlat +towgs84=225.571,-346.608,-46.567,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + STPM50GEO : "+title=St Pierre et Miquelon 1950 +proj=longlat +towgs84=-95.5930,573.7630,173.4420,-0.9602,1.2510,-1.3918,42.626500 +a=6378206.4000 +rf=294.9786982000000 +units=m +no_defs", + TAHAAGEO : "+title=Raiatea - Tahaa 51-54 (Tahaa, Base Terme Est) +proj=longlat +towgs84=72.4380,345.9180,79.4860,-1.6045,-0.8823,-0.5565,1.374600 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + TAHI79GEO : "+title=IGN79 (Tahiti) Iles de la Societe +proj=longlat +towgs84=221.5250,152.9480,176.7680,2.3847,1.3896,0.8770,11.474100 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + TERA50G : "+title=Pointe Geologie - Perroud 1950 +proj=longlat +towgs84=324.9120,153.2820,172.0260 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + WALL78GEO : "+title=Wallis - Uvea 1978 (MOP78) +proj=longlat +towgs84=253.0000,-133.0000,-127.0000 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs", + WGS72G : "+title=WGS72 +proj=longlat +towgs84=0.0000,12.0000,6.0000 +a=6378135.0000 +rf=298.2600000000000 +units=m +no_defs", + WGS84G : "+title=World Geodetic System 1984 +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + WGS84RRAFGEO : "+title=Reseau de reference des Antilles francaises (1988-1991) +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + XGEO : "+title=Systeme CIO-BIH +proj=longlat +towgs84=0.0000,0.0000,0.5000,0.0000,0.0000,0.0140,-0.100000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + AMST63UTM43S : "+title=Amsterdam 1963 UTM fuseau 43 Sud +proj=tmerc +towgs84=109.753,-528.133,-362.244,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=75.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + CROZ63UTM39S : "+title=Crozet 1963 +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=51.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + CSG67UTM21 : "+title=Guyane CSG67 UTM fuseau 21 +proj=tmerc +towgs84=-193.0660,236.9930,105.4470,0.4814,-0.8074,0.1276,1.564900 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-57.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + CSG67UTM22 : "+title=Guyane CSG67 UTM fuseau 22 +proj=tmerc +towgs84=-193.0660,236.9930,105.4470,0.4814,-0.8074,0.1276,1.564900 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-51.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + GEOPORTALANF : "+title=Geoportail - Antilles francaises +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=15.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + GEOPORTALASP : "+title=Geoportail - Amsterdam et Saint-Paul +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-38.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + GEOPORTALCRZ : "+title=Geoportail - Crozet +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-46.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + GEOPORTALFXX : "+title=Geoportail - France metropolitaine +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=46.500000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + GEOPORTALGUF : "+title=Geoportail - Guyane +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=4.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + GEOPORTALKER : "+title=Geoportail - Kerguelen +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-49.500000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + GEOPORTALMYT : "+title=Geoportail - Mayotte +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-12.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + GEOPORTALNCL : "+title=Geoportail - Nouvelle-Caledonie +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-22.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + GEOPORTALPYF : "+title=Geoportail - Polynesie francaise +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-15.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + GEOPORTALREU : "+title=Geoportail - Reunion et dependances +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-21.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + GEOPORTALSPM : "+title=Geoportail - Saint-Pierre et Miquelon +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=47.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + GEOPORTALWLF : "+title=Geoportail - Wallis et Futuna +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-14.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + GUAD48UTM20 : "+title=Guadeloupe Ste Anne +proj=tmerc +towgs84=-472.2900,-5.6300,-304.1200,0.4362,-0.8374,0.2563,1.898400 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-63.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + GUADFM49U20 : "+title=Guadeloupe Fort Marigot +proj=tmerc +towgs84=136.5960,248.1480,-429.7890 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-63.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + IGN63UTM7S : "+title=IGN 1963 - Hiva Oa, Tahuata, Mohotani - UTM fuseau 7 Sud +proj=tmerc +towgs84=410.7210,55.0490,80.7460,-2.5779,-2.3514,-0.6664,17.331100 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-141.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + IGN72UTM58S : "+title=IGN 1972 - UTM fuseau 58 Sud +proj=tmerc +towgs84=-11.6400,-348.6000,291.6800 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=165.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + KERG62UTM42S : "+title=Kerguelen 1962 +proj=tmerc +towgs84=144.8990,-186.7700,100.9230 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=69.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + LAMB1 : "+title=Lambert I +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=49.500000000 +lon_0=0.000000000 +k_0=0.99987734 +lat_1=49.500000000 +x_0=600000.000 +y_0=200000.000 +units=m +no_defs", + LAMB1C : "+title=Lambert I Carto +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=49.500000000 +lon_0=0.000000000 +k_0=0.99987734 +lat_1=49.500000000 +x_0=600000.000 +y_0=1200000.000 +units=m +no_defs", + LAMB2 : "+title=Lambert II +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=46.800000000 +lon_0=0.000000000 +k_0=0.99987742 +lat_1=46.800000000 +x_0=600000.000 +y_0=200000.000 +units=m +no_defs", + LAMB2C : "+title=Lambert II Carto +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=46.800000000 +lon_0=0.000000000 +k_0=0.99987742 +lat_1=46.800000000 +x_0=600000.000 +y_0=2200000.000 +units=m +no_defs", + LAMB3 : "+title=Lambert III +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=44.100000000 +lon_0=0.000000000 +k_0=0.99987750 +lat_1=44.100000000 +x_0=600000.000 +y_0=200000.000 +units=m +no_defs", + LAMB3C : "+title=Lambert III Carto +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=44.100000000 +lon_0=0.000000000 +k_0=0.99987750 +lat_1=44.100000000 +x_0=600000.000 +y_0=3200000.000 +units=m +no_defs", + LAMB4 : "+title=Lambert IV +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=42.165000000 +lon_0=0.000000000 +k_0=0.99994471 +lat_1=42.165000000 +x_0=234.358 +y_0=185861.369 +units=m +no_defs", + LAMB4C : "+title=Lambert IV Carto +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=42.165000000 +lon_0=0.000000000 +k_0=0.99994471 +lat_1=42.165000000 +x_0=234.358 +y_0=4185861.369 +units=m +no_defs", + LAMB93 : "+title=Lambert 93 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=46.500000000 +lon_0=3.000000000 +lat_1=44.000000000 +lat_2=49.000000000 +x_0=700000.000 +y_0=6600000.000 +units=m +no_defs", + RGF93CC42 : "+title=Lambert conique conforme Zone 1 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=42.000000000 +lon_0=3.000000000 +lat_1=41.200000000 +lat_2=42.800000000 +x_0=1700000.000 +y_0=1200000.000 +units=m +no_defs", + RGF93CC43 : "+title=Lambert conique conforme Zone 2 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=43.000000000 +lon_0=3.000000000 +lat_1=42.200000000 +lat_2=43.800000000 +x_0=1700000.000 +y_0=2200000.000 +units=m +no_defs", + RGF93CC44 : "+title=Lambert conique conforme Zone 3 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=44.000000000 +lon_0=3.000000000 +lat_1=43.200000000 +lat_2=44.800000000 +x_0=1700000.000 +y_0=3200000.000 +units=m +no_defs", + RGF93CC45 : "+title=Lambert conique conforme Zone 4 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=45.000000000 +lon_0=3.000000000 +lat_1=44.200000000 +lat_2=45.800000000 +x_0=1700000.000 +y_0=4200000.000 +units=m +no_defs", + RGF93CC46 : "+title=Lambert conique conforme Zone 5 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=46.000000000 +lon_0=3.000000000 +lat_1=45.200000000 +lat_2=46.800000000 +x_0=1700000.000 +y_0=5200000.000 +units=m +no_defs", + RGF93CC47 : "+title=Lambert conique conforme Zone 6 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=47.000000000 +lon_0=3.000000000 +lat_1=46.200000000 +lat_2=47.800000000 +x_0=1700000.000 +y_0=6200000.000 +units=m +no_defs", + RGF93CC48 : "+title=Lambert conique conforme Zone 7 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=48.000000000 +lon_0=3.000000000 +lat_1=47.200000000 +lat_2=48.800000000 +x_0=1700000.000 +y_0=7200000.000 +units=m +no_defs", + RGF93CC49 : "+title=Lambert conique conforme Zone 8 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=49.000000000 +lon_0=3.000000000 +lat_1=48.200000000 +lat_2=49.800000000 +x_0=1700000.000 +y_0=8200000.000 +units=m +no_defs", + RGF93CC50 : "+title=Lambert conique conforme Zone 9 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=50.000000000 +lon_0=3.000000000 +lat_1=49.200000000 +lat_2=50.800000000 +x_0=1700000.000 +y_0=9200000.000 +units=m +no_defs", + LAMBE : "+title=Lambert II etendu +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=46.800000000 +lon_0=0.000000000 +k_0=0.99987742 +lat_1=46.800000000 +x_0=600000.000 +y_0=2200000.000 +units=m +no_defs", + MART38UTM20 : "+title=Martinique Fort-Desaix +proj=tmerc +towgs84=126.9260,547.9390,130.4090,-2.7867,5.1612,-0.8584,13.822650 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-63.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + MAYO50UTM38S : "+title=Mayotte Combani +proj=tmerc +towgs84=-599.9280,-275.5520,-195.6650,-0.0835,-0.4715,0.0602,49.281400 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=45.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + MILLER : "+title=Geoportail - Monde +proj=mill +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lon_0=0.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs", + MOOREA87U6S : "+title=Moorea 1987 - UTM fuseau 6 Sud +proj=tmerc +towgs84=215.9820,149.5930,176.2290,3.2624,1.6920,1.1571,10.477300 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-147.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + NUKU72U7S : "+title=IGN 1972 Nuku Hiva - UTM fuseau 7 Sud +proj=tmerc +towgs84=165.7320,216.7200,180.5050,-0.6434,-0.4512,-0.0791,7.420400 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-141.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + // REUN47GAUSSL : "+title=Reunion Gauss Laborde +proj=gstmerc +towgs84=789.5240,-626.4860,-89.9040,0.6006,76.7946,-10.5788,-32.324100 +a=6378388.0000 +rf=297.0000000000000 +lat_0=-21.116666667 +lon_0=55.533333333 +k_0=1.00000000 +x_0=160000.000 +y_0=50000.000 +units=m +no_defs", + RGM04UTM38S : "+title=UTM fuseau 38 Sud (Reseau Geodesique de Mayotte 2004) +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=45.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + RGNCUTM57S : "+title=Reseau Geodesique de Nouvelle-Caledonie - UTM fuseau 57 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=159.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + RGNCUTM58S : "+title=Reseau Geodesique de Nouvelle-Caledonie - UTM fuseau 58 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=165.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + RGNCUTM59S : "+title=Reseau Geodesique de Nouvelle-Caledonie - UTM fuseau 59 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=171.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + RGPFUTM5S : "+title=RGPF - UTM fuseau 5 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-153.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + RGPFUTM6S : "+title=RGPF - UTM fuseau 6 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-147.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + RGPFUTM7S : "+title=RGPF - UTM fuseau 7 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-141.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + RGR92UTM40S : "+title=RGR92 UTM fuseau 40 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=57.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + RGSPM06U21 : "+title=Saint-Pierre-et-Miquelon (2006) UTM Fuseau 21 Nord +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-57.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + STPL69UTM43S : "+title=Saint-Paul 1969 UTM fuseau 43 Sud +proj=tmerc +towgs84=225.571,-346.608,-46.567,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=75.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + STPM50UTM21 : "+title=St Pierre et Miquelon 1950 +proj=tmerc +towgs84=-95.5930,573.7630,173.4420,-0.9602,1.2510,-1.3918,42.626500 +a=6378206.4000 +rf=294.9786982000000 +lat_0=0.000000000 +lon_0=-57.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + TAHAAUTM05S : "+title=Tahaa 1951 +proj=tmerc +towgs84=72.4380,345.9180,79.4860,-1.6045,-0.8823,-0.5565,1.374600 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-153.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + TAHI51UTM06S : "+title=Tahiti-Terme Nord UTM fuseau 6 Sud +proj=tmerc +towgs84=162.0000,117.0000,154.0000 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-147.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + TAHI79UTM6S : "+title=Tahiti 1979 +proj=tmerc +towgs84=221.5250,152.9480,176.7680,2.3847,1.3896,0.8770,11.474100 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-147.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + TERA50STEREO : "+title=Terre Adelie 1950 +proj=stere +towgs84=324.9120,153.2820,172.0260 +a=6378388.0000 +rf=297.0000000000000 +lat_0=-90.000000000 +lon_0=140.000000000 +lat_ts=-67 +k=0.96027295 +x_0=300000.000 +y_0=-2299363.482 +units=m +no_defs", + UTM01SW84 : "+title=World Geodetic System 1984 UTM fuseau 01 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-177.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + UTM20W84GUAD : "+title=World Geodetic System 1984 UTM fuseau 20 Nord-Guadeloupe +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-63.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM20W84MART : "+title=World Geodetic System 1984 UTM fuseau 20 Nord-Martinique +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-63.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM22RGFG95 : "+title=RGFG95 UTM fuseau 22 Nord-Guyane +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-51.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM39SW84 : "+title=World Geodetic System 1984 UTM fuseau 39 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=51.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + UTM42SW84 : "+title=World Geodetic System 1984 UTM fuseau 42 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=69.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + UTM43SW84 : "+title=World Geodetic System 1984 UTM fuseau 43 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=75.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + WALL78UTM1S : "+title=Wallis-Uvea 1978 (MOP78) UTM 1 SUD +proj=tmerc +towgs84=253.0000,-133.0000,-127.0000 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-177.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs", + ETRS89GEO : "+title=ETRS89 geographiques (dms) +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs", + ETRS89LAEA : "+title=ETRS89 Lambert Azimutal Equal Area +proj=laea +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=52.000000000 +lon_0=10.000000000 +x_0=4321000.000 +y_0=3210000.000 +units=m +no_defs", + ETRS89LCC : "+title=ETRS89 Lambert Conformal Conic +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=52.000000000 +lon_0=9.999999995 +lat_1=35.000000000 +lat_2=65.000000000 +x_0=4000000.000 +y_0=2800000.000 +units=m +no_defs", + UTM26ETRS89 : "+title=Europe - de 30d a 24d Ouest +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-27.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM27ETRS89 : "+title=Europe - de 24d a 18d Ouest +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-21.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM28ETRS89 : "+title=Europe - de 18d a 12d Ouest +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-15.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM29ETRS89 : "+title=Europe - de 12d a 6d Ouest +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-9.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM30ETRS89 : "+title=Europe - de -6d a 0d Ouest +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-3.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM31ETRS89 : "+title=Europe - de 0d a 6d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=3.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM32ETRS89 : "+title=Europe - de 6d a 12d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=9.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM33ETRS89 : "+title=Europe - de 12d a 18d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=15.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM34ETRS89 : "+title=Europe - de 18d a 24d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=21.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM35ETRS89 : "+title=Europe - de 24d a 30d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=27.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM36ETRS89 : "+title=Europe - de 30d a 36d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=33.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM37ETRS89 : "+title=Europe - de 36d a 42d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=39.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs", + UTM38ETRS89 : "+title=Europe - de 42d a 48d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=45.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs" + } +}; + +export default Register; diff --git a/src/Common-review/Utils/SearchEngineUtils.js b/src/Common-review/Utils/SearchEngineUtils.js new file mode 100644 index 000000000..666a72f6d --- /dev/null +++ b/src/Common-review/Utils/SearchEngineUtils.js @@ -0,0 +1,145 @@ +var SearchEngineUtils = { + /** + * Advanced Search Filters by default + */ + advancedSearchFiltersByDefault : { + PositionOfInterest : [{ + name : "importance", + title : "Importance" + }, { + name : "nature", + title : "Nature" + }, { + name : "territory", + title : "Territoire" + }, { + name : "insee", + title : "Code INSEE" + }, { + name : "municipality", + title : "Ville" + }, { + name : "department", + title : "Département" + }], + StreetAddress : [ + // INFO + // ce ne sont pas des filtres mais une location dite structurée ! + // {name : "number", title : "Numéro"}, + // {name : "street", title : "Rue"}, + // {name : "postalCode", title : "Code Postal"}, + // {name : "city", title : "Commune"}, + { + name : "territory", + title : "Territoire" + }, { + name : "insee", + title : "Code INSEE" + }, { + name : "municipality", + title : "Ville" + }, { + name : "department", + title : "Département" + } + ], + CadastralParcel : [{ + name : "department", + title : "Département", + description : "Numéro du département (ex: 01, 94)" + }, { + name : "commune", + title : "Code commune (INSEE)", + description : "Code commune (INSEE) : 3 chiffres (ex: 067)" + }, + // { + // name : "insee", + // title : "Code INSEE" + // }, + { + name : "absorbedCity", + title : "Commune absorbée", + description : "Commune absorbée : 3 chiffres (ex: 000, 001)" + }, { + name : "section", + title : "Section", + description : "Section : 2 caractères (ex: AA, 0D)" + }, { + name : "number", + title : "Numéro", + description : "Numéro de la parcelle : 4 chiffres (ex: 0041, 0250)" + } + ], + Administratif : [{ + name : "prefecture", + title : "Préfecture" + }, { + name : "inseeRegion", + title : "Code région (INSEE)" + }, { + name : "inseeDepartment", + title : "Code département (INSEE)" + }, { + name : "municipality", + title : "Ville" + }] + }, + + /** + * Provides default zoom based on results. + * + * @param {Object} info - location information + * @returns {Integer} zoom level + */ + zoomToResultsByDefault : function (info) { + // FIXME + // la classification du geocodage est differente de l'importance de l'autocompletion ! + + var zoom = 15; + + var service = info.service; + var fields = info.fields; + var type = info.type; + + var importance = { + 1 : 11, + 2 : 12, + 3 : 13, + 4 : 14, + 5 : 15, + 6 : 16, + 7 : 17, + 8 : 17 + }; + + // AutoCompletion POI + if (service === "SuggestedLocation") { + if (type === "PositionOfInterest") { + zoom = importance[fields.classification]; + } + } + + // Geocodage POI + if (service === "DirectGeocodedLocation") { + if (type === "PositionOfInterest") { + zoom = importance[fields.importance] || 14; // au cas où la recherche est en freeform ! + } + } + + if (type === "StreetAddress") { + zoom = 17; + } + + if (type === "CadastralParcel") { + zoom = 17; + } + + if (type === "Administratif") { + zoom = 12; + } + + return zoom; + } +}; + +export default SearchEngineUtils; diff --git a/src/Common-review/Utils/SelectorID.js b/src/Common-review/Utils/SelectorID.js new file mode 100644 index 000000000..d5b0dc6d1 --- /dev/null +++ b/src/Common-review/Utils/SelectorID.js @@ -0,0 +1,80 @@ +/** + * formalisme d'un tag ID : + * -> NAME(_ORDER)-1460636385836 + * + * Ex. + * GProutePoints-1460636385836 + * GProutePoint_10-1460636385836 + */ +var SelectorID = { + + /** + * Construction d'un identifiant statique basé sur le timestamp, + * et qui s'incremente de +1 à chaque appel + */ + generate : (function () { + var timestamp = Math.floor(Date.now()); + return function () { + return timestamp++; + }; + })(), + + /** + * nom du tag + * @param {String} id - the id + * + * @returns {String} index + */ + name : function (id) { + var name = null; + + var i = id.lastIndexOf("-"); + if (i === -1) { + name = id; + } else { + name = id.substring(0, i); + } + + return name; + }, + + /** + * numero d'identifiant du tag + * @param {String} id - the id + * + * @returns {String} index + */ + index : function (id) { + var index = null; + + var name = this.name(id); + // if (name !== id) { + var i = name.lastIndexOf("_"); + if (i !== -1) { + index = name.substring(i + 1); + } + // } + + return index; + }, + + /** + * uuid du tag + * @param {String} id - the id + * + * @returns {String} uuid + */ + uuid : function (id) { + var uuid = null; + + var i = id.lastIndexOf("-"); + if (i !== -1) { + uuid = parseInt(id.substring(i + 1), 10); + } + + return uuid; + } + +}; + +export default SelectorID; diff --git a/src/Itowns-review/CRS/CRS.js b/src/Itowns-review/CRS/CRS.js new file mode 100644 index 000000000..b38835df4 --- /dev/null +++ b/src/Itowns-review/CRS/CRS.js @@ -0,0 +1,204 @@ +var CRS = { + + /** + * CRS : WGS84 + * + * @property EPSG:4326 + * @private + */ + "EPSG:4326" : "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +units=degrees", + + /** + * CRS : PseudoMercator + * + * @property EPSG:3857 + * @private + */ + "EPSG:3857" : "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs", + + /** + * CRS : Lambert 93 + * + * @property EPSG:2154 + * @private + */ + "EPSG:2154" : "+proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs", + + /** + * CRS : Lambert 2 extended + * + * @property EPSG:27572 + * @private + */ + "EPSG:27572" : "+proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs", + + /** + * CRS : UTM 20N (Guadeloupe, Martinique) + * + * @property EPSG:32620 + * @private + */ + "EPSG:32620" : "+proj=utm +zone=20 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", + + /** + * CRS : UTM 21N (Saint-Pierre-et-Miquelon) + * + * @property EPSG:4467 + * @private + */ + "EPSG:4467" : "+proj=utm +zone=21 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs", + + /** + * CRS : UTM 22N (Guyane) + * + * @property EPSG:2972 + * @private + */ + "EPSG:2972" : "+proj=utm +zone=22 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs", + + /** + * CRS : UTM 30N (France métropolitaine) + * + * @property EPSG:32630 + * @private + */ + "EPSG:32630" : "+proj=utm +zone=30 +datum=WGS84 +units=m +no_defs", + + /** + * CRS : UTM 31N (France métropolitaine) + * + * @property EPSG:32631 + * @private + */ + "EPSG:32631" : "+proj=utm +zone=31 +datum=WGS84 +units=m +no_defs", + + /** + * CRS : UTM 32N (France métropolitaine) + * + * @property EPSG:32632 + * @private + */ + "EPSG:32632" : "+proj=utm +zone=32 +datum=WGS84 +units=m +no_defs", + + /** + * CRS : UTM 38S (Mayotte) + * + * @property EPSG:4471 + * @private + */ + "EPSG:4471" : "+proj=utm +zone=38 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs", + + /** + * CRS : UTM 40S (Réunion) + * + * @property EPSG:2975 + * @private + */ + "EPSG:2975" : "+proj=utm +zone=40 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs", + + /** + * CRS : UTM 5S (Polynésie) + * + * @property EPSG:3296 + * @private + */ + "EPSG:3296" : "+proj=utm +zone=5 +south +ellps=GRS80 +towgs84=0.072,-0.507,-0.245,-0.0183,0.0003,-0.007,-0.0093 +units=m +no_defs", + + /** + * CRS : UTM 6S (Polynésie) + * + * @property EPSG:3297 + * @private + */ + "EPSG:3297" : "+proj=utm +zone=6 +south +ellps=GRS80 +towgs84=0.072,-0.507,-0.245,-0.0183,0.0003,-0.007,-0.0093 +units=m +no_defs", + + /** + * CRS : UTM 7S (Polynésie) + * + * @property EPSG:32707 + * @private + */ + "EPSG:32707" : "+proj=utm +zone=7 +south +datum=WGS84 +units=m +no_defs", + + /** + * CRS : UTM 8S (Polynésie) + * + * @property EPSG:32708 + * @private + */ + "EPSG:32708" : "+proj=utm +zone=8 +south +datum=WGS84 +units=m +no_defs", + + /** + * CRS : UTM 12N (Ile de Clipperton) + * + * @property EPSG:26912 + * @private + */ + "EPSG:26912" : "+proj=utm +zone=12 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs", + + /** + * CRS : UTM 42S (Iles Kerguelen) + * + * @property EPSG:32742 + * @private + */ + "EPSG:32742" : "+proj=utm +zone=42 +south +datum=WGS84 +units=m +no_defs", + + /** + * CRS : UTM 39S (Iles Crozet) + * + * @property EPSG:32739 + * @private + */ + "EPSG:32739" : "+proj=utm +zone=39 +south +datum=WGS84 +units=m +no_defs", + + /** + * CRS : UTM 43S (Iles St-Paul et Amsterdam) + * + * @property EPSG:32743 + * @private + */ + "EPSG:32743" : "+proj=utm +zone=43 +south +datum=WGS84 +units=m +no_defs", + + /** + * CRS : Stéréographique polaire (Terre Adelie) + * + * @property EPSG:2986 + * @private + */ + "EPSG:2986" : "", + + /** + * CRS : UTM 37S (Iles du canal de Mozambique) + * + * @property EPSG:32737 + * @private + */ + "EPSG:32737" : "+proj=utm +zone=37 +south +datum=WGS84 +units=m +no_defs", + + /** + * CRS : UTM 38S (Iles du canal de Mozambique) + * + * @property EPSG:32738 + * @private + */ + "EPSG:32738" : "+proj=utm +zone=38 +south +datum=WGS84 +units=m +no_defs", + + /** + * CRS : UTM 1S (Wallis-et-Futuna) + * + * @property EPSG:2988 + * @private + */ + "EPSG:2988" : "+proj=utm +zone=1 +south +ellps=intl +towgs84=253,-132,-127,0,0,0,0 +units=m +no_defs", + + /** + * CRS : RGNC91-93 (Nouvelle-Calédonie) + * + * @property EPSG:3163 + * @private + */ + "EPSG:3163" : "+proj=lcc +lat_1=-20.66666666666667 +lat_2=-22.33333333333333 +lat_0=-21.5 +lon_0=166 +x_0=400000 +y_0=300000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs" +}; + +export default CRS; diff --git a/src/Itowns-review/CSS/Controls/Attribution/GPattributionItowns.css b/src/Itowns-review/CSS/Controls/Attribution/GPattributionItowns.css new file mode 100644 index 000000000..686655603 --- /dev/null +++ b/src/Itowns-review/CSS/Controls/Attribution/GPattributionItowns.css @@ -0,0 +1,66 @@ +div[id^=GPAttribution-] { + display: flex; + bottom: 8px; + right: 8px; + width: calc(90% - 1.3em); +} + +div[id^=GPAttributionsListContainer-] { + display: none; + width: 80%; + height: 80%; + background: white; + opacity: 0.5; + border-radius: 4px; + z-index: 0; + position: absolute; +} + +div[id^=GPAttributionsListContainer-] ul { + display: flex; + margin: auto; + list-style: none; +} + +label[id^=GPshowAttributionsListPicto-] { + display: flex; + z-index: 1; + position: relative; + margin-left: auto; +} + +input[id^=GPshowAttributionsList-]:checked + div[id^=GPAttributionsListContainer-] { + display: flex; +} + +input[id^=GPshowAttributionsList-]:checked + div[id^=GPAttributionsListContainer-] + label[id^=GPshowAttributionsListPicto-] { + background-color: transparent; +} + +span[id^=GPshowAttributionsListOpenClose-] { + color: #fff; + font-size: 1.6em; + font-weight: 700; + text-align: center; + line-height: 1.2em; +} + +div[id^=GPAttributionsListContainer-] li:before { + content: " | "; +} + +div[id^=GPAttributionsListContainer-] ul li:nth-child(1):before { + content: ""; +} + +div[id^=GPAttributionsListContainer-] ul li:first-child:before { + content: ""; +} + +div[id^=GPAttributionsListContainer-] a:link { + text-decoration: none; +} + +div[id^=GPAttributionsListContainer-] a:visited { + text-decoration: none; +} diff --git a/src/Itowns-review/CSS/Controls/BoostRelief/GPboostReliefItowns.css b/src/Itowns-review/CSS/Controls/BoostRelief/GPboostReliefItowns.css new file mode 100644 index 000000000..a183b9068 --- /dev/null +++ b/src/Itowns-review/CSS/Controls/BoostRelief/GPboostReliefItowns.css @@ -0,0 +1,74 @@ +/* BOOST RELIEF ITOWNS */ + +div[id^=GPboostRelief-] { + top: 8px; + left: 8px; +} + +/* Showing/hiding boostRelief panel */ +label[id^=GPshowBoostReliefPicto-] { + display: flex; + z-index: 1; + position: relative; + margin-left: auto; +} + +label[id^=GPshowBoostReliefListPicto-] { + display: flex; + z-index: 1; + position: relative; +} + +/* +span[id^=GPshowBoostReliefOpenClose-] { + color: #fff; + font-size: 1.6em; + font-weight: 700; + text-align: center; + line-height: 1.2em; +}*/ + +span[id^="GPshowBoostReliefOpenClose-"] { + background-image: url("img/GPboostReliefOpen.png"); +} + +.spanClose span[id^="GPshowBoostReliefOpenClose-"] { + background-position: 0 0; +} + +.spanOpen span[id^="GPshowBoostReliefOpenClose-"] { + background-position: -26px 0; +} + +/* +div[id^=GPboostRelief-] input[type="checkbox"]:checked + div + label[id^=GPshowBoostReliefPicto] span[id^=GPshowBoostReliefOpen] { + opacity: 0.7; +} + +div[id^=GPboostRelief-] input[type="checkbox"]:checked + div + label[id^=GPshowBoostReliefPicto] span[id^=GPshowBoostReliefClose] { + background-color: rgba(0,60,136,0.3); +} + +div[id^=GPboostRelief-] input[type="checkbox"]:checked + div + label[id^=GPshowBoostReliefPicto] :hover span[id^=GPshowBoostReliefClose] { + background-color: rgba(0,60,136,0.4); +} + +*/ + +/* Relief slider : Chrome, Safari, Opera */ + +.GPlayerRelief input[type="range"]::-webkit-slider-runnable-track { + background: url("img/GPreliefSlider.png"); +} + +/* Relief slider : Firefox */ + +.GPlayerRelief input[type="range"]::-moz-range-track { + background: url("img/GPreliefSlider.png"); +} + +/* Relief slider : IE */ + +.GPlayerRelief input[type="range"]::-ms-track { + background: url("img/GPreliefSlider.png"); +} diff --git a/src/Itowns-review/CSS/Controls/BoostRelief/img/GPboostReliefOpen.png b/src/Itowns-review/CSS/Controls/BoostRelief/img/GPboostReliefOpen.png new file mode 100644 index 000000000..d083722cc Binary files /dev/null and b/src/Itowns-review/CSS/Controls/BoostRelief/img/GPboostReliefOpen.png differ diff --git a/src/Itowns-review/CSS/Controls/BoostRelief/img/GPreliefSlider.png b/src/Itowns-review/CSS/Controls/BoostRelief/img/GPreliefSlider.png new file mode 100644 index 000000000..301e289bc Binary files /dev/null and b/src/Itowns-review/CSS/Controls/BoostRelief/img/GPreliefSlider.png differ diff --git a/src/Itowns-review/CSS/Controls/LayerSwitcher/GPlayerSwitcherItowns.css b/src/Itowns-review/CSS/Controls/LayerSwitcher/GPlayerSwitcherItowns.css new file mode 100644 index 000000000..ecc932010 --- /dev/null +++ b/src/Itowns-review/CSS/Controls/LayerSwitcher/GPlayerSwitcherItowns.css @@ -0,0 +1,91 @@ +/* LAYER SWITCHER OL3 */ + +div[id^=GPlayerSwitcher-] { + top: 8px; + right: 8px; +} + +/* Showing/hiding layers list */ + +label[id^=GPshowLayersListPicto] { + width: 38px; + height: 38px; +} + +span[id^=GPshowLayersListOpen] , +span[id^=GPshowLayersListClose] { + top: 3px; + left: 3px; + width: 32px; + height: 32px; + background-image: url("img/GPshowLayersList.png"); +} + +span[id^=GPshowLayersListClose] { + background-position: -32px 0; +} + + +div[id^=GPlayerSwitcher-] input[type="checkbox"]:checked + div + label[id^=GPshowLayersListPicto] span[id^=GPshowLayersListOpen] { + opacity: 0.7; +} + +div[id^=GPlayerSwitcher-] input[type="checkbox"]:checked + div + label[id^=GPshowLayersListPicto] span[id^=GPshowLayersListClose] { + background-color: rgba(0,60,136,0.3); +} + +div[id^=GPlayerSwitcher-] input[type="checkbox"]:checked + div + label[id^=GPshowLayersListPicto] :hover span[id^=GPshowLayersListClose] { + background-color: rgba(0,60,136,0.4); +} + +/* Layers list */ + +.GPlayerVisibility, +.GPshowLayerAdvancedTools, +.GPlayerInfo, +.GPlayerInfoOpened, +.GPlayerRemove { + background-image: url("img/GPlayerTools.png"); +} + +/* Opacity slider : Chrome, Safari, Opera */ + +.GPlayerOpacity input[type="range"]::-webkit-slider-runnable-track { + background: url("img/GPopacitySlider.png"); +} + +/* Opacity slider : Firefox */ + +.GPlayerOpacity input[type="range"]::-moz-range-track { + background: url("img/GPopacitySlider.png"); +} + +/* Opacity slider : IE */ + +.GPlayerOpacity input[type="range"]::-ms-track { + background: url("img/GPopacitySlider.png"); +} + +/* Layer info panel */ + +div[id^=GPlayerInfoPanel] { + right: 190px; +} + +div[id^=GPlayerInfoTitle] { + color: #366291; + border-bottom: 1px solid #366291; +} + +div[id^=GPlayerInfoQuicklook] { + background-image: url("img/GPlayerInfo.png"); +} + +div[id^=GPlayerInfoClose] { + background-image: url("img/GPlayerInfoClose.png"); +} + +.GPlayerInfoLink, +.GPlayerInfoPopup { + background-image: url("img/GPlayerInfo.png"); +} diff --git a/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerInfo.png b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerInfo.png new file mode 100644 index 000000000..b7d5a0be8 Binary files /dev/null and b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerInfo.png differ diff --git a/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerInfoClose.png b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerInfoClose.png new file mode 100644 index 000000000..1d61d5dec Binary files /dev/null and b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerInfoClose.png differ diff --git a/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerTools.png b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerTools.png new file mode 100644 index 000000000..6c696c089 Binary files /dev/null and b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerTools.png differ diff --git a/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPopacitySlider.png b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPopacitySlider.png new file mode 100644 index 000000000..301e289bc Binary files /dev/null and b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPopacitySlider.png differ diff --git a/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPshowLayersList.png b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPshowLayersList.png new file mode 100644 index 000000000..9f4c4fd30 Binary files /dev/null and b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPshowLayersList.png differ diff --git a/src/Itowns-review/CSS/Controls/MiniGlobe/GPminiGlobeItowns.css b/src/Itowns-review/CSS/Controls/MiniGlobe/GPminiGlobeItowns.css new file mode 100644 index 000000000..5da731735 --- /dev/null +++ b/src/Itowns-review/CSS/Controls/MiniGlobe/GPminiGlobeItowns.css @@ -0,0 +1,8 @@ +div[id^=GPminiglobeContainer-] { + display: block; + width:100px; + height:100px; + left: 20px; + bottom: 20px; + color: white; +} diff --git a/src/Itowns-review/CSS/Controls/MousePosition/GPmousePositionItowns.css b/src/Itowns-review/CSS/Controls/MousePosition/GPmousePositionItowns.css new file mode 100644 index 000000000..ffe326dc0 --- /dev/null +++ b/src/Itowns-review/CSS/Controls/MousePosition/GPmousePositionItowns.css @@ -0,0 +1,30 @@ +/* MOUSE POSITION */ + +div[id^=GPmousePosition-] { + bottom: 8px; + left: 10px; +} + +/* Showing/hiding mouse position panel */ + +span[id^=GPshowMousePositionOpen] { + background-image: url("img/GPmousePositionOpen.png"); +} + +/* General panels */ + +div[id^=GPmousePositionPanel-] { + position: relative; + left: 0px; + top: 0px; +} + +div[id^=GPmousePositionPanelClose] { + background-image: url("img/GPmousePositionOpen.png"); +} + +/* Map center localisation */ + +#GPmapCenter { + background-image: url("img/GPmapCenter.png"); +} diff --git a/src/Itowns-review/CSS/Controls/MousePosition/img/GPmapCenter.png b/src/Itowns-review/CSS/Controls/MousePosition/img/GPmapCenter.png new file mode 100644 index 000000000..a10837a90 Binary files /dev/null and b/src/Itowns-review/CSS/Controls/MousePosition/img/GPmapCenter.png differ diff --git a/src/Itowns-review/CSS/Controls/MousePosition/img/GPmousePositionOpen.png b/src/Itowns-review/CSS/Controls/MousePosition/img/GPmousePositionOpen.png new file mode 100644 index 000000000..142f8f98a Binary files /dev/null and b/src/Itowns-review/CSS/Controls/MousePosition/img/GPmousePositionOpen.png differ diff --git a/src/Itowns-review/CSS/Controls/Scale/GPscaleItowns.css b/src/Itowns-review/CSS/Controls/Scale/GPscaleItowns.css new file mode 100644 index 000000000..83a84dd10 --- /dev/null +++ b/src/Itowns-review/CSS/Controls/Scale/GPscaleItowns.css @@ -0,0 +1,15 @@ +div[id^=GPscaleContainer-] { + border: 2px solid white; + border-top: none; + text-align: center; + display: block; + background-image: linear-gradient(rgba(200, 200, 200, 0.3), rgba(200, 200, 200, 0.3)); + height: 18px; + width: 200px; + color: white; + font-family: 'Open Sans', + sans-serif; + font-size: 16px; + right: 20px; + bottom: 20px; +} diff --git a/src/Itowns-review/CSS/GPgeneralWidgetItowns.css b/src/Itowns-review/CSS/GPgeneralWidgetItowns.css new file mode 100644 index 000000000..9a0d6b4e0 --- /dev/null +++ b/src/Itowns-review/CSS/GPgeneralWidgetItowns.css @@ -0,0 +1,67 @@ +/* General panels */ + +.GPpanel { + box-shadow: 0 0 6px #000; + border-radius: 4px; +} + +.GPpanelHeader { + height: 32px; + padding: 3px; + background-color: #9DB1BD; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +.GPpanelTitle { + line-height: 26px; + border-top-left-radius: 2px; + border-top-right-radius: 2px; + background-color: #366291; + color: #FFF; +} + +.GPpanelClose { + top: 3px; + right: 3px; + width: 26px; + height: 26px; + background-position: -26px 0; +} + +/* Showing/hiding advanced panels */ + +.GPshowAdvancedToolPicto { + width: 32px; + height: 32px; + padding: 3px; + background-color: rgba(255, 255, 255, 0.4); + border-radius: 4px; +} + +.GPshowAdvancedToolPicto:hover { + background-color: rgba(255, 255, 255, 0.6); +} + +.GPshowAdvancedToolOpen { + width: 26px; + height: 26px; + background-color: rgba(0,60,136,0.5); + border-radius: 2px; +} + +.GPshowAdvancedToolPicto:hover .GPshowAdvancedToolOpen { + background-color: rgba(0,60,136,0.7); +} + +/* Submit inputs */ + +input.GPinputSubmit { + background-color: #366291; +} + +/* Showing additional hidden options */ + +.GPshowMoreOptionsImage { + background-image: url("img/GPshowMoreOptions.png"); +} diff --git a/src/Itowns-review/CSS/img/GPshowMoreOptions.png b/src/Itowns-review/CSS/img/GPshowMoreOptions.png new file mode 100644 index 000000000..fc109295c Binary files /dev/null and b/src/Itowns-review/CSS/img/GPshowMoreOptions.png differ diff --git a/src/Itowns-review/Controls/Attributions.js b/src/Itowns-review/Controls/Attributions.js new file mode 100644 index 000000000..306c35c98 --- /dev/null +++ b/src/Itowns-review/Controls/Attributions.js @@ -0,0 +1,318 @@ +import GlobeViewExtended from "../GlobeViewExtended"; +import Logger from "../../Common/Utils/LoggerByDefault"; +import Utils from "../../Common/Utils"; +import SelectorID from "../../Common/Utils/SelectorID"; +import LayerUtils from "../../Common/Utils/LayerUtils"; +import AttributionDOM from "../../Common/Controls/AttributionDOM"; +import Widget from "./Widget"; + +var logger = Logger.getLogger("Attributions"); + +/** + * @classdesc + * Control to manage layers attributions + * + * @constructor + * @alias itowns.control.Attributions + * @extends {itowns.control.Widget} + * @param {Object} aOptions - control options + * @param {Object} [aOptions.options] - Itowns.control.Control options + * @param {Boolean} [aOptions.options.collapsed = false] - Specify if the control has to be opened or not. + * @example + * var attribution = new itowns.control.Attritbution({ + * options : { + * collapsed: true + * } + * )); + */ +function Attributions (aOptions) { + aOptions = aOptions || {}; + var options = aOptions.options || {}; + + if (!(this instanceof Attributions)) { + throw new TypeError("ERROR CLASS_CONSTRUCTOR"); + } + + if (options && typeof options !== "object") { + throw new Error("ERROR WRONG_TYPE : options should be an object"); + } + + this._initialize(options); + + var container = this._initContainer(options); + + Widget.call( + this, { + name : "Attributions", + element : container, + target : options.target, + position : options.position + } + ); +} + +/* + * @lends module:Attributions + */ +Attributions.prototype = Object.create(Widget.prototype, {}); + +// retrieves methods of the common class AttributionDOM +Utils.assign(Attributions.prototype, AttributionDOM); + +/** + * Constructor (alias) + * + * @private + */ +Attributions.prototype.constructor = Attributions; + +// ################################################################### // +// ############## public methods (getters, setters) ################## // +// ################################################################### // + +/** + * Bind globe to control + * + * @param {GlobeViewExtended} globe - the globe + */ +Attributions.prototype.setGlobe = function (globe) { + // info : this function is called after a globe.addWidget() or a globe.removeWidget() + + if (globe) { // In the case of the adding of a control to the globe + var self = this; + + // Adding of the listeners + + // At every globe movement, attributions may be updated, + // according to layers on globe, and their visibility. + this._callbacks.onPreRenderCallBack = function (e) { + var allLayers = e.colorLayersId.concat(e.elevationLayersId); + + self._inRangeUpdate(allLayers, e.extent); + }; + + globe.listen(GlobeViewExtended.EVENTS.PRE_RENDER, this._callbacks.onPreRenderCallBack); + globe.preRenderEventFetchViewExtent(); + globe.preRenderEventFetchLayersDisplayed(); + } else { + // delete listener + this._globe.forget(GlobeViewExtended.EVENTS.PRE_RENDER, this._callbacks.onPreRenderCallBack); + + // delete DOM + while (this._element.hasChildNodes()) { + this._element.removeChild(this._element.lastChild); + } + this._element.parentNode.removeChild(this._element); + } + + // call original setGlobe method + Widget.prototype.setGlobe.call(this, globe); +}; + +/** + * Collapse or display control main container + * + * @param {Boolean} collapsed - True to collapse control, False to display it + */ +Attributions.prototype.setCollapsed = function (collapsed) { + if (collapsed === undefined) { + logger.error("Attributions:setCollapsed - missing collapsed parameter"); + return; + } + var isCollapsed = this.getCollapsed(); + if ((collapsed && isCollapsed) || (!collapsed && !isCollapsed)) { + return; + } + + document.getElementById(this._addUID("GPshowAttributionsList")).checked = !collapsed; +}; + +/** + * Returns true if widget is collapsed (minimize), false otherwise + * + * @return {Boolean} collapsed + */ +Attributions.prototype.getCollapsed = function () { + return !document.getElementById(this._addUID("GPshowAttributionsList")).checked; +}; + +// ################################################################### // +// ##################### init component ############################## // +// ################################################################### // + +/** + * Initialize Attributions control (called by constructor) + * + * @param {Object} options - Itowns.control.Control options + * @private + */ +Attributions.prototype._initialize = function (options) { + // id of the widget : usefull to suffix the CSS ids (to handle cases with several widgets on the same page) + this._uid = SelectorID.generate(); + + // div which will contain the list divs. + this._AttributionContainer = null; + + // callbacks + this._callbacks = {}; + + // options + this._options = options; +}; + +/** + * Creates control main container + * + * @method _initContainer + * @param {Object} options - control options + * @returns {DOMElement} container - widget container + * @private + */ +Attributions.prototype._initContainer = function (options) { + var container = this._createMainContainerElement(); + + // adds in the main container the layer display selector + var inputShow = this._createMainAttributionsShowElement(); + container.appendChild(inputShow); + + // handles the "collapsed" mode + if (!options.collapsed) { + inputShow.checked = "checked"; + } + // adds the layer list in the main container + var divA = this._attributionListContainer = this._createMainAttributionsListContainer(); + var ulA = this._createAttributionsList(); + divA.appendChild(ulA); + container.appendChild(divA); + + // adds the widget picto in the main container + var picto = this._createMainPictoElement(options.collapsed); + container.appendChild(picto); + + return container; +}; + +/** + * Checks layers range + * + * @method _inRangeUpdate + * @param {Array} layersDisplayed - Id of the layers diplayed on screen + * @param {Object} extent - The globe view extent + * @private + */ + +Attributions.prototype._inRangeUpdate = function (layersDisplayed, extent) { + var globe = this.getGlobe(); + + var scaleDenominator = 1 / globe.getScale(); + + var attributions = new Map(); + + for (var h = 0; h < layersDisplayed.length; h++) { + var layer = globe.getLayerById(layersDisplayed[h]); + + var ori = layer.source.attribution; + + if (ori) { + for (var j = 0; j < ori.length; j++) { + // if the attribution is already added, we skip to not add it several times + if (attributions.has(ori[j].name)) { + continue; + }; + // if no constraints are associated to the originator, we just add the attribution + if (!ori[j].constraints || !ori[j].constraints[0]) { + // adds the attribution in the Map() called 'attributions' + attributions.set(ori[j].name, ori[j]); + continue; + } + // if the minScaleDenominator exists + if (ori[j].constraints[0].minScaleDenominator) { + // if min/maxScaleDenominator are equals, we display the attribution corresponding to the zoom level associated to the scale denominator + if (ori[j].constraints[0].minScaleDenominator === ori[j].constraints[0].maxScaleDenominator) { + // retrieves the zoom level + var attributionZoomLevel = LayerUtils.getZoomLevelFromScaleDenominator(ori[j].constraints[0].minScaleDenominator); + // selects the scaledenominators around the corresponding zoom level + var maxAttributionScaleDenominator = (this._resolutionsWGS84[attributionZoomLevel] + this._resolutionsWGS84[attributionZoomLevel - 1]) / (0.00028 * 2); + var minAttributionScaleDenominator = (this._resolutionsWGS84[attributionZoomLevel] + this._resolutionsWGS84[attributionZoomLevel + 1]) / (0.00028 * 2); + if (!(maxAttributionScaleDenominator > scaleDenominator && scaleDenominator > minAttributionScaleDenominator)) { + continue; + } + // either, we check we are located between the minScaleDenominator and the maxScaleDenominator + } else if (!(ori[j].constraints[0].minScaleDenominator < scaleDenominator && scaleDenominator < ori[j].constraints[0].maxScaleDenominator)) { + continue; + } + } + // checks if 'bbox" exists + if (ori[j].constraints[0].bbox) { + // checks if we are into the bbox limits + var intersectsX = (ori[j].constraints[0].bbox.left <= extent.east) && (extent.west <= ori[j].constraints[0].bbox.right); + var intersectsY = (ori[j].constraints[0].bbox.bottom <= extent.north) && (extent.south <= ori[j].constraints[0].bbox.top); + if (intersectsX && intersectsY) { + // adds the attribution in the Map() called 'attributions' + attributions.set(ori[j].name, ori[j]); + } + // if 'bbox' attribute doesn't exist + } else if (!ori[j].constraints[0].bbox) { + attributions.set(ori[j].name, ori[j]); + } + } + } + } + this._updateAttributionListContainer(attributions); +}; + +// ################################################################### // +// ######################### DOM events ############################## // +// ################################################################### // + +/** + * Updates the layer list container + * + * @method _updateAttributionListContainer + * @param {Map} attributions - map of attributions + * @private + */ +Attributions.prototype._updateAttributionListContainer = function (attributions) { + var element = document.getElementById(this._addUID("GPAttributionsList")); + document.getElementById(this._addUID("GPAttributionsList")).parentNode.removeChild(element); + + var ul = this._createAttributionsList(); + attributions.forEach(function (a) { + var li = document.createElement("li"); + var link = document.createElement("a"); + link.href = a.url; + link.innerHTML = a.name + " "; + link.target = "_blank"; + li.id = a.name.replace(/\s/g, ""); + li.appendChild(link); + ul.appendChild(li); + }); + this._attributionListContainer.appendChild(ul); +}; + +Attributions.prototype._resolutionsWGS84 = { + 0 : 156543.033928041, + 1 : 78271.51696402048, + 2 : 39135.758482010235, + 3 : 19567.87924100512, + 4 : 9783.93962050256, + 5 : 4891.96981025128, + 6 : 2445.98490512564, + 7 : 1222.99245256282, + 8 : 611.49622628141, + 9 : 305.7481131407048, + 10 : 152.8740565703525, + 11 : 76.43702828517624, + 12 : 38.21851414258813, + 13 : 19.10925707129406, + 14 : 9.554628535647032, + 15 : 4.777314267823516, + 16 : 2.388657133911758, + 17 : 1.194328566955879, + 18 : 0.5971642834779395, + 19 : 0.2985821417389697, + 20 : 0.1492910708694849, + 21 : 0.0746455354347424 +}; + +export default Attributions; diff --git a/src/Itowns-review/Controls/BoostRelief.js b/src/Itowns-review/Controls/BoostRelief.js new file mode 100644 index 000000000..266b3c77f --- /dev/null +++ b/src/Itowns-review/Controls/BoostRelief.js @@ -0,0 +1,281 @@ +import Logger from "../../Common/Utils/LoggerByDefault"; +import Utils from "../../Common/Utils"; +import SelectorID from "../../Common/Utils/SelectorID"; +import BoostReliefDOM from "../../Common/Controls/BoostReliefDOM"; +import Widget from "./Widget"; + +var logger = Logger.getLogger("BoostRelief"); + +/** + * @classdesc + * Control to manage globe layers : their order, visibility and relief, and display their informations (title, description, legends, metadata...) + * + * @constructor + * @extends {itowns.control.Widget} + * @alias itowns.control.BoostRelief + * @param {Object} brOptions - control options + * @param {Object} [brOptions.scale] - Defines the scale used to boost the relief + * @param {Number} [brOptions.scale.min] - Minimum of the scale - 1 by default + * @param {Number} [brOptions.scale.max] - Maximum of the scale - 50 by default + * @param {Number} [brOptions.scale.step] - Step of the scale - 1 by default + * @param {Boolean} [brOptions.collapsed = true] - Specify if widget has to be collapsed (true) or not (false) on globe loading. + * @param {Boolean} [brOptions.defaultBoost = 1] - Default boost value applied to the widget and the elevation layers when loaded + * @example + * var boostRelief = new itowns.control.BoostRelief({ + * scale : { + * max : 30, + * step : 2 + * }, + * defaultBoost : 6 + * }) + */ +function BoostRelief (brOptions) { + brOptions = brOptions || {}; + var options = brOptions.options || {}; + + if (!(this instanceof BoostRelief)) { + throw new TypeError("ERROR CLASS_CONSTRUCTOR"); + } + + if (options && typeof options !== "object") { + throw new Error("ERROR WRONG_TYPE : options should be an object"); + } + + this._initialize(); + + var container = this._initContainer(brOptions); + var targetDiv = document.getElementById(options.target) || null; + + Widget.call( + this, { + name : "BoostRelief", + element : container, + target : targetDiv + } + ); +} + +/* + * @lends module:BoostRelief + */ +BoostRelief.prototype = Object.create(Widget.prototype, {}); + +// retrieves methods of the common class BoostReliefDOM +Utils.assign(BoostRelief.prototype, BoostReliefDOM); + +/** + * Constructor (alias) + * + * @private + */ +BoostRelief.prototype.constructor = BoostRelief; + +// ################################################################### // +// ############## public methods (getters, setters) ################## // +// ################################################################### // + +/** + * Bind globe to control + * + * @param {GlobeViewExtended} globe - the globe + */ +BoostRelief.prototype.setGlobe = function (globe) { + // TODO - removing listeners + // this._globe.removeLayerListener(layers[j], GlobeViewExtended.EVENTS.Relief_PROPERTY_CHANGED, this._callbacks.onReliefLayerCallBack); + // deletes the layerSwitcher DOM + if (!globe) { + while (this._element.hasChildNodes()) { + this._element.removeChild(this._element.lastChild); + } + this._element.parentNode.removeChild(this._element); + } + // calls original setGlobe method + Widget.prototype.setGlobe.call(this, globe); +}; + +/** + * Collapse or display control main container + * + * @param {Boolean} collapsed - True to collapse control, False to display it + */ +BoostRelief.prototype.setCollapsed = function (collapsed) { + if (collapsed === undefined) { + logger.error("BoostRelief:setCollapsed - missing collapsed parameter"); + return; + } + if (typeof collapsed !== "boolean") { + logger.error("BoostRelief:setCollapsed - collapsed parameter is not a boolean"); + return; + } + var isCollapsed = this.getCollapsed(); + + if ((collapsed && isCollapsed) || (!collapsed && !isCollapsed)) { + return; + } + var controlDiv = document.getElementById(this._addUID("GPBoostReliefListContainer")); + if (collapsed) { + controlDiv.style.display = "block"; + document.getElementById(this._addUID("GPshowBoostReliefList")).checked = true; + } else { + controlDiv.style.display = "none"; + document.getElementById(this._addUID("GPshowBoostReliefList")).checked = false; + } +}; + +/** + * Returns true if widget is collapsed (minimize), false otherwise + * @return {Boolean} is collapsed + */ +BoostRelief.prototype.getCollapsed = function () { + return document.getElementById(this._addUID("GPshowBoostReliefList")).checked; +}; + +// ################################################################### // +// ##################### init component ############################## // +// ################################################################### // + +/** + * Initialize BoostRelief control (called by constructor) + * + * @private + */ +BoostRelief.prototype._initialize = function () { + // id of the control ; used to suffix the CSS id (handles cases with severel controls on the same page) + this._uid = SelectorID.generate(); + + // {Object} control layers list. Each key is a layer id, and its value is an object of layers options (layer, id, relief, visibility, title, description...) + this._layers = {}; + + // callbacks + this._callbacks = {}; +}; + +/** + * Creates control main container + * + * @method _initContainer + * @param {Object} brOptions - control options + * @returns {DOMElement} container - widget container + * @private + */ +BoostRelief.prototype._initContainer = function (brOptions) { + var container = this._createMainContainerElement(); + + // adds in the main container the layer display selector + var inputShow = this._createMainBoostReliefShowElement(brOptions.collapsed); + container.appendChild(inputShow); + + // adds the layer list in the main container + var divA = this._boostReliefListContainer = this._createMainBoostReliefListContainer(); + var boostReliefList = this._createAdvancedToolElement(brOptions); + + divA.appendChild(boostReliefList); + container.appendChild(divA); + + // adds the widget picto in the main container + var picto = this._createMainPictoElement(); + container.appendChild(picto); + + if (brOptions.collapsed) { + divA.style.display = "block"; + } else { + divA.style.display = "none"; + } + + return container; +}; + +// ################################################################### // +// ######################### DOM events ############################## // +// ################################################################### // + +/** + * Changes layer relief on layer relief picto click + * + * @method _onChangeLayerRelief + * @param {Object} e - HTML event + * @private + */ +BoostRelief.prototype._onChangeLayerRelief = function (e) { + + var reliefValue = parseInt(e.target.value); + var reliefId = document.getElementById(this._addUID("GPreliefValue")); + + reliefId.innerHTML = "x" + reliefValue; + + this._updateLayersRelief(reliefValue); +}; + +/** + * Updates relief values of all elevation layers + * + * @method _updateLayerRelief + * @param {Number} reliefValue - relief value + * @private + */ + +BoostRelief.prototype._updateLayersRelief = function (reliefValue) { + var globe = this.getGlobe(); + + function updateScale (layer, value) { + layer.scale = value; + globe.notifyChange(layer); + } + // if the scale of a single elevationLayer change, we update the scale of all others + var elevationLayers = globe.getElevationLayers(); + + for (var i = 0; i < elevationLayers.length; i++) { + updateScale(elevationLayers[i], reliefValue); + } + +}; + +/** + * Updates relief slider and all elevation layers with the given boost value + * + * @method changeBoost + * @param {Number} reliefValue - relief value + */ +BoostRelief.prototype.changeBoost = function (reliefValue) { + var layerReliefInput = document.getElementById(this._addUID("GPreliefValueDiv")); + + if (!layerReliefInput) { + logger.error("BoostRelief:changeBoost - boostRelief slider not loaded"); + return; + } + + // the reliefValue given must me in the slider range + if (reliefValue > layerReliefInput.max) { + reliefValue = layerReliefInput.max; + } + if (reliefValue < layerReliefInput.min) { + reliefValue = layerReliefInput.min; + } + + // updates the relief of all the elevationlayers + this._updateLayersRelief(reliefValue); + + // updates the slider cursor + layerReliefInput.value = reliefValue; + + // updates the slider text + var layerReliefSpan = document.getElementById(this._addUID("GPreliefValue")); + if (layerReliefSpan) { + layerReliefSpan.innerHTML = "x" + reliefValue; + } +}; + +/** + * Gets layer id from div id + * + * @method _resolveLayerId + * @param {String} divId - HTML div id + * @returns {String} layer id + * @private + */ +BoostRelief.prototype._resolveLayerId = function (divId) { + var divName = SelectorID.name(divId); // ex GPvisibilityPicto_ID_26 + return divName.substring(divName.indexOf("_ID_") + 4); // ex. 26 +}; + +export default BoostRelief; diff --git a/src/Itowns-review/Controls/LayerSwitcher.js b/src/Itowns-review/Controls/LayerSwitcher.js new file mode 100644 index 000000000..e15c56e73 --- /dev/null +++ b/src/Itowns-review/Controls/LayerSwitcher.js @@ -0,0 +1,909 @@ +import GlobeViewExtended from "../GlobeViewExtended"; +import Logger from "../../Common/Utils/LoggerByDefault"; +import Utils from "../../Common/Utils"; +import SelectorID from "../../Common/Utils/SelectorID"; +import LayerSwitcherDOM from "../../Common/Controls/LayerSwitcherDOM"; +import Widget from "./Widget"; + +var logger = Logger.getLogger("LayerSwitcher"); + +/** + * @classdesc + * Control to manage globe layers : their order, visibility and opacity, and display their informations (title, description, legends, metadata...) + * + * @constructor + * @extends {itowns.control.Widget} + * @alias itowns.control.LayerSwitcher + * @param {Object} lsOptions - control options + * @param {Array} [lsOptions.layers] - list of layers to be configured. Each array element is an object, with following properties : + * @param {String} [lsOptions.layers.id] - ol.layer.Layer layer to be configured (that has been added to globe) + * @param {Object} [lsOptions.layers.config] - custom configuration object for layer information (title, description, legends, metadata, quicklook url), with following properties : + * @param {String} [lsOptions.layers.config.title] - layer alias, to be displayed in widget layer list. E.g. : "Cartes IGN" + * @param {String} [lsOptions.layers.config.description] - layer description, to be displayed on title hover, or in layer information panel. + * @param {String} [lsOptions.layers.config.quicklookUrl] - link to a quick look image for this layer. + * @param {Array} [lsOptions.layers.config.legends] - array of layer legends. Each array element is an object, with following properties : + * - url (String, mandatory) : link to a legend + * - minScaleDenominator (Number, optional) : min scale denominator for legend validity. + * @param {Array} [lsOptions.layers.config.metadata] - array of layer metadata. Each array element is an object, with property url (String, mandatory) : link to a metadata + * @param {Object} [lsOptions.options] - Itowns.control.Control options + * @param {Boolean} [lsOptions.options.collapsed = true] - Specify if widget has to be collapsed (true) or not (false) on globe loading. + * @example + * var layerSwitcher = new itowns.control.LayerSwitcher({ + * layers : [ + * { + * id : "myLayer", + * config : { + * title : "test layer name 1", + * description : "test layer desc 1", + * } + * } + * ], + * options : { + * collapsed : false + * } + * )); + */ +function LayerSwitcher (lsOptions) { + lsOptions = lsOptions || {}; + var options = lsOptions.options || {}; + var layers = lsOptions.layers || []; + + if (!(this instanceof LayerSwitcher)) { + throw new TypeError("ERROR CLASS_CONSTRUCTOR"); + } + + if (layers && !Array.isArray(layers)) { + throw new Error("ERROR WRONG_TYPE : layers should be an array"); + } + + if (options && typeof options !== "object") { + throw new Error("ERROR WRONG_TYPE : options should be an object"); + } + + this._initialize(options, layers); + + var container = this._initContainer(options); + // property to save layers conf added after the LS is initialized + this._addedLayerConf = {}; + + Widget.call( + this, { + name : "LayerSwitcher", + element : container, + target : options.target, + position : options.position + } + ); +} + +/* + * @lends module:LayerSwitcher + */ +LayerSwitcher.prototype = Object.create(Widget.prototype, {}); + +// retrieves methods of the common class LayerSwitcherDOM +Utils.assign(LayerSwitcher.prototype, LayerSwitcherDOM); + +/** + * Constructor (alias) + * + * @private + */ +LayerSwitcher.prototype.constructor = LayerSwitcher; + +// ################################################################### // +// ############## public methods (getters, setters) ################## // +// ################################################################### // + +/** + * Bind globe to control + * + * @param {GlobeViewExtended} globe - the globe + */ +LayerSwitcher.prototype.setGlobe = function (globe) { + var layers; + if (globe) { // in the case the control is added to the globe + var self = this; + + // add options layers to layerlist. + // (only the layers configurated by the user in the options of the layerSwitcher ) + // the other layers of the map will be added in the setGlobe method + for (var i = 0; i < this._initLayers.length; i++) { + // retrieves the layer... + var layer = null; + + if (this._initLayers[i].id) { + layer = globe.getLayerById(this._initLayers[i].id); + } + + if (layer && this._initLayers[i].displayed) { + // .. and the infos of the configuration if they exist (title, description, legends, quicklook, metadata) + var conf = this._initLayers[i].config || {}; + var layerOptions = { + title : conf.title || layer.title || this._initLayers[i].id, + description : conf.description || null, + legends : conf.legends || [], + metadata : conf.metadata || [], + quicklookUrl : conf.quicklookUrl || null + }; + if (typeof conf.ipr !== "undefined") { + layerOptions.ipr = conf.ipr; + } + if (typeof conf.opacity !== "undefined") { + layerOptions.opacity = conf.opacity; + } + if (typeof conf.visibility !== "undefined") { + layerOptions.visibility = conf.visibility; + } + this._layers[layer.id] = layerOptions; + } + } + + // adds the layers + this._addGlobeLayers(globe); + + // adding of listeners + this._callbacks.onOpacityLayerCallBack = function (e) { + self._updateLayerOpacity(e.target.id, e.new.opacity); + }; + + this._callbacks.onVisibilityLayerCallBack = function (e) { + self._updateLayerVisibility(e.target.id, e.new.visible); + }; + + // At every globe movement, layer switcher may be updated, + // according to layers on globe, and their range. + this._callbacks.onChangedViewCallBack = function (e) { + self._inRangeUpdate(e.colorLayersId); + }; + globe.listen(GlobeViewExtended.EVENTS.PRE_RENDER, this._callbacks.onChangedViewCallBack); + // prerender events returns visible layers + globe.preRenderEventFetchColorLayersDisplayed(); + + this._callbacks.onAddedLayerCallBack = function (e) { + var id = e.layerId; + if (self) { + if (!self._layerDisplayedInLayerSwitcher(id)) { + return; + } + var layer = self.getGlobe().getLayerById(id); + if (layer.type === "elevation") { + return; + } + var layerConf = self._getLayerConf(id) || self._addedLayerConf[id]; + if (layerConf) { + self.addLayer(layer, layerConf); + } else { + self.addLayer(layer); + } + } + }; + globe.listen(GlobeViewExtended.EVENTS.LAYER_ADDED, this._callbacks.onAddedLayerCallBack); + + this._callbacks.onRemovedLayerCallBack = function (e) { + var id = e.layerId; + + // update the index max and delete the layer from the layerswitcher + if (self) { + self.removeLayer(id); + } + }; + globe.listen(GlobeViewExtended.EVENTS.LAYER_REMOVED, this._callbacks.onRemovedLayerCallBack); + + this._callbacks.onIndexLayerCallBack = function (e) { + var arraysEquals = function (a1, a2) { + if (a1.length !== a2.length) { + return false; + } + for (var i = 0; i < a1.length; ++i) { + if (a1[i] !== a2[i]) { + return false; + } + } + return true; + }; + + if (!arraysEquals(e.new.sequence, e.previous.sequence)) { + self._updateLayerListContainer(); + } + }; + globe.listen(GlobeViewExtended.EVENTS.LAYERS_ORDER_CHANGED, this._callbacks.onIndexLayerCallBack); + + layers = globe.getColorLayers(); + for (var ii = 0; ii < layers.length; ++ii) { + globe.addLayerListener(layers[ii], GlobeViewExtended.EVENTS.OPACITY_PROPERTY_CHANGED, this._callbacks.onOpacityLayerCallBack); + globe.addLayerListener(layers[ii], GlobeViewExtended.EVENTS.VISIBLE_PROPERTY_CHANGED, this._callbacks.onVisibilityLayerCallBack); + self._updateLayerVisibility(layers[ii].id, layers[ii].visible); + self._updateLayerOpacity(layers[ii].id, layers[ii].opacity); + } + } else { + // removes the listeners associated to the deleted layerswitcher + this._globe.forget(GlobeViewExtended.EVENTS.PRE_RENDER, this._callbacks.onChangedViewCallBack); + this._globe.forget(GlobeViewExtended.EVENTS.LAYER_ADDED, this._callbacks.onAddedLayerCallBack); + this._globe.forget(GlobeViewExtended.EVENTS.LAYER_REMOVED, this._callbacks.onRemovedLayerCallBack); + this._globe.forget(GlobeViewExtended.EVENTS.LAYERS_ORDER_CHANGED, this._callbacks.onIndexLayerCallBack); + layers = this._globe.getColorLayers(); + for (var j = 0; j < layers.length; ++j) { + this._globe.removeLayerListener(layers[j], GlobeViewExtended.EVENTS.OPACITY_PROPERTY_CHANGED, this._callbacks.onOpacityLayerCallBack); + this._globe.removeLayerListener(layers[j], GlobeViewExtended.EVENTS.VISIBLE_PROPERTY_CHANGED, this._callbacks.onVisibilityLayerCallBack); + } + // deletes the layerSwitcher DOM + while (this._element.hasChildNodes()) { + this._element.removeChild(this._element.lastChild); + } + this._element.parentNode.removeChild(this._element); + } + + // calls original setGlobe method + Widget.prototype.setGlobe.call(this, globe); +}; + +/** + * Adds a new layer to control (when added to globe) or add new layer configuration + * + * @param {Object} layer - layer to add to layer switcher + * @param {Object} [config] - additional options for layer configuration + * @param {Object} [config.title] - layer title (default is layer identifier) + * @param {Object} [config.description] - layer description (default is null) + * @param {Object} [config.legends] - layer legends (default is an empty array) + * @param {Object} [config.metadata] - layer metadata (default is an empty array) + * @param {Object} [config.quicklookUrl] - layer quicklookUrl (default is null) + * @example + * layerSwitcher.addLayer({ + * layer : gpParcels, + * config : { + * title : "Parcelles cadastrales", + * description : "description de la couche", + * quicklookUrl : "http://quicklookUrl.fr" + * } + * }) + */ +LayerSwitcher.prototype.addLayer = function (layer, config) { + config = config || {}; + var globe = this.getGlobe(); + + if (!layer) { + logger.error("LayerSwitcher:addLayer - missing layer parameter"); + return; + } + + var id = layer.id; + if (id === "undefined") { + logger.error("LayerSwitcher:addLayer - configuration cannot be set for " + layer + " layer (layer id not found)"); + return; + } + + // subscription to the events + globe.addLayerListener(layer, GlobeViewExtended.EVENTS.OPACITY_PROPERTY_CHANGED, this._callbacks.onOpacityLayerCallBack); + globe.addLayerListener(layer, GlobeViewExtended.EVENTS.VISIBLE_PROPERTY_CHANGED, this._callbacks.onVisibilityLayerCallBack); + + // make sure layer is in globe layers + var LayerInGlobe = globe.getLayerById(id); + + if (!LayerInGlobe) { + logger.error("LayerSwitcher:addLayer - configuration cannot be set for ", layer, " layer (layer is not in globe layers )"); + return; + } + + // if layer is not already in layers list, add it to control (layers list and container div) + if (!this._layers[id]) { + // 1. add layer to layers list + var layerInfos = this._getLayerInfo(layer) || {}; + var layerOptions = { + title : config.title || layerInfos._title || id, + description : config.description || layerInfos._description || null, + legends : config.legends || layerInfos._legends || [], + metadata : config.metadata || layerInfos._metadata || [], + quicklookUrl : config.quicklookUrl || layerInfos._quicklookUrl || null + }; + if (typeof config.ipr !== "undefined") { + layerOptions.ipr = config.ipr; + layer.attribution = layerOptions.ipr; + } + if (typeof config.opacity !== "undefined") { + layerOptions.opacity = config.opacity; + layer.opacity = layerOptions.opacity; + } + if (typeof config.visibility !== "undefined") { + layerOptions.visibility = config.visibility; + layer.visible = layerOptions.visibility; + } + this._layers[id] = layerOptions; + + // creation of the div of the layer which will be added to the layerSwitcher + this._layers[id].div = this._createLayerDiv(id); + + this._updateLayerListContainer(); + + // user may also add a new configuration for an already added layer + } else if (this._layers[id] && config) { + // add new configuration parameters to layer informations + for (var prop in config) { + if (config.hasOwnProperty(prop)) { + this._layers[id][prop] = config[prop]; + } + } + if (typeof config.ipr !== "undefined") { + layer.attribution = config.ipr; + } + if (typeof config.opacity !== "undefined") { + layer.opacity = config.opacity; + } + if (typeof config.visibility !== "undefined") { + layer.visible = config.visibility; + } + // set new title in layer div + if (config.title) { + var nameDiv = document.getElementById(this._addUID("GPname_ID_" + id)); + if (nameDiv) { + nameDiv.innerHTML = config.title; + // FIXME a ajouter? + // nameDiv.title = config.description || config.title; + } + } + // add layer info picto if necessary + var infodiv = document.getElementById(this._addUID("GPinfo_ID_" + id)); + if (!document.getElementById(this._addUID("GPinfo_ID_" + id)) && config.description && (config.legends || config.metadata || config.quicklookUrl)) { + var advancedTools = document.getElementById(this._addUID("GPadvancedTools_ID_" + id)); + if (advancedTools) { + advancedTools.appendChild( + this._createAdvancedToolInformationElement({ + id : id + }) + ); + } + } + // close layer info element if open, to update information. + if (infodiv && infodiv.className === "GPlayerInfoOpened") { + document.getElementById(this._addUID("GPlayerInfoPanel")).className = "GPlayerInfoPanelClosed"; + infodiv.className = "GPlayerInfo"; + } + } +}; + +/** + * Removes a layer from control + * + * @param {Object} layerId - layer to remove to layer switcher + */ +LayerSwitcher.prototype.removeLayer = function (layerId) { + var layerList = document.getElementById(this._addUID("GPlayersList")); + // close layer info element if open. + var infodiv = document.getElementById(this._addUID("GPinfo_ID_" + layerId)); + if (infodiv && infodiv.className === "GPlayerInfoOpened") { + document.getElementById(this._addUID("GPlayerInfoPanel")).className = "GPlayerInfoPanelClosed"; + infodiv.className = "GPlayerInfo"; + } + // remove layer div + var layerDiv = document.getElementById(this._addUID("GPlayerSwitcher_ID_" + layerId)); + layerList.removeChild(layerDiv); + + // removes layer of the layer list + delete this._layers[layerId]; +}; + +/** + * Collapse or display control main container + * + * @param {Boolean} collapsed - True to collapse control, False to display it + */ +LayerSwitcher.prototype.setCollapsed = function (collapsed) { + if (collapsed === undefined) { + logger.error("LayerSwitcher:setCollapsed - missing collapsed parameter"); + return; + } + var isCollapsed = this.getCollapsed(); + if ((collapsed && isCollapsed) || (!collapsed && !isCollapsed)) { + return; + } + // simulates the panel opening after a click + if (!isCollapsed) { + var layers = document.getElementsByClassName("GPlayerInfoOpened"); + for (var i = 0; i < layers.length; i++) { + layers[i].className = "GPlayerInfo"; + } + document.getElementById(this._addUID("GPlayerInfoPanel")).className = "GPlayerInfoPanelClosed"; + } + document.getElementById(this._addUID("GPshowLayersList")).checked = !collapsed; +}; + +/** + * Returns true if widget is collapsed (minimize), false otherwise + * @return {Boolean} is collapsed + */ +LayerSwitcher.prototype.getCollapsed = function () { + return !document.getElementById(this._addUID("GPshowLayersList")).checked; +}; + +// ################################################################### // +// ##################### init component ############################## // +// ################################################################### // + +/** + * Initialize LayerSwitcher control (called by constructor) + * + * @param {Object} options - Itowns.control.Control options + * @param {Array} layers - list of layers to be configured. Each array element is an object, with following properties : + * @private + */ +LayerSwitcher.prototype._initialize = function (options, layers) { + // id of the control ; used to suffix the CSS id (handles cases with severel controls on the same page) + this._uid = SelectorID.generate(); + + // {Object} control layers list. Each key is a layer id, and its value is an object of layers options (layer, id, opacity, visibility, title, description...) + this._layers = {}; + + // div which will contain the divs of the lists + this._layerListContainer = null; + + // callbacks + this._callbacks = {}; + + // options + this._options = options; + this._initLayers = layers; +}; + +/** + * Returns the layer configuration defined at widget initialization + * + * @method _getLayerConf + * @param {String} layerId - layer id + * @return {Object} layerConfig - layer configuration + * @private + */ +LayerSwitcher.prototype._getLayerConf = function (layerId) { + for (var i = 0; i < this._initLayers.length; ++i) { + if (this._initLayers[i].id === layerId) { + return this._initLayers[i].config; + } + } + return null; +}; + +/** + * Indicates if the layer must be displayed in the layerSwitcher + * + * @method _layerDisplayedInLayerSwitcher + * @param {String} layerId - layer id + * @return {Boolean} displayed + * @private + */ +LayerSwitcher.prototype._layerDisplayedInLayerSwitcher = function (layerId) { + for (var i = 0; i < this._initLayers.length; ++i) { + if (this._initLayers[i].id === layerId) { + return (typeof this._initLayers[i].displayed === "undefined" || this._initLayers[i].displayed); + } + } + return true; +}; + +/** + * Creates control main container + * + * @method _initContainer + * @param {Object} options - control options + * @returns {DOMElement} container - widget container + * @private + */ +LayerSwitcher.prototype._initContainer = function (options) { + // creation of the main container + var container = this._createMainContainerElement(); + + // adding in the main container + var input = this._createMainLayersShowElement(); + container.appendChild(input); + + // handling of the "collapsed" mode + if (!options.collapsed) { + input.checked = "checked"; + } + // adds the layer list in the main container + var divL = this._layerListContainer = this._createMainLayersElement(); + container.appendChild(divL); + + // creates the draggable mode + this._createDraggableElement(divL, this); + + // adds the control picto in the main container + var picto = this._createMainPictoElement(); + container.appendChild(picto); + + // adds the info panel in the main container + var divI = this._createMainInfoElement(); + container.appendChild(divI); + + return container; +}; + +/** + * Adds control layers to control main container + * + * @method _addGlobeLayers + * @param {Object} globe - the Itowns.GlobeViewExtended object + * @private + */ +LayerSwitcher.prototype._addGlobeLayers = function (globe) { + // Retrieves the element which contains the different layers + var elementLayersList; + var childNodes = this.getElement().childNodes; + + for (var i = 0; i < childNodes.length; i++) { + if (childNodes[i].id === this._addUID("GPlayersList")) { + elementLayersList = childNodes[i]; + break; + } + } + // reorders layers according to the layer stack (globe.getLayers returns an reverse ordenered array) + var layers = globe.getColorLayers(); + var orderedLayers = layers.sort(function (a, b) { + return b.sequence - a.sequence; + }); + + // loop over all the layers of the map in order to add them to the control layer list (if they are not already added) + orderedLayers.forEach( + function (layer) { + // adds the map layers to the list + var id; + id = layer.id; + if (!this._layerDisplayedInLayerSwitcher(id)) { + return; + } + var layerConf = this._getLayerConf(id) || this._addedLayerConf[id] || {}; + var layerInfos = this._getLayerInfo(layer) || {}; + if (!this._layers[id]) { + // if the layer is not yet in the layer list (this._layers), we add it + var layerOptions = { + title : layerConf.title || layerInfos._title || id, + description : layerConf.description || layerInfos._description || null, + legends : layerConf.legends || layerInfos._legends || [], + metadata : layerConf.metadata || layerInfos._metadata || [], + quicklookUrl : layerConf.quicklookUrl || layerInfos._quicklookUrl || null + }; + this._layers[id] = layerOptions; + } else { + var lsLayerConf = this._layers[id]; + if (typeof lsLayerConf.ipr !== "undefined") { + layer.options.attribution = lsLayerConf.ipr; + } + if (typeof lsLayerConf.opacity !== "undefined") { + layer.opacity = lsLayerConf.opacity; + } + if (typeof lsLayerConf.visibility !== "undefined") { + layer.visible = lsLayerConf.visibility; + } + } + + var layerDiv = this._createLayerDiv(id); + this._layers[id].div = layerDiv; + elementLayersList.appendChild(layerDiv); + }, + this + ); +}; + +/** + * creates layer div (to append to control DOM element). + * + * @method _createLayerDiv + * @param {String} layerId - layer id + * @returns {DOMElement} layer div + * @private + */ +LayerSwitcher.prototype._createLayerDiv = function (layerId) { + var layerOptions = this._layers[layerId]; + var isLegends = layerOptions.legends && layerOptions.legends.length !== 0; + var isMetadata = layerOptions.metadata && layerOptions.metadata.length !== 0; + var isQuicklookUrl = layerOptions.quicklookUrl; + if (isLegends || isMetadata || isQuicklookUrl) { + layerOptions.displayInformationElement = true; + } + + // adds a specific div in the control for the layer + layerOptions.id = layerId; + var layerDiv = this._createContainerLayerElement(layerOptions); + + if (!layerOptions.inRange) { + layerDiv.classList.add("outOfRange"); + } + + return layerDiv; +}; + +// ################################################################### // +// ######################### DOM events ############################## // +// ################################################################### // + +/** + * Changes layer opacity on layer opacity picto click + * + * @method _onChangeLayerOpacity + * @param {Object} e - HTML event + * @private + */ +LayerSwitcher.prototype._onChangeLayerOpacity = function (e) { + var globe = this.getGlobe(); + var layerID = this._resolveLayerId(e.target.id); + + var opacityValue = e.target.value; + var opacityId = document.getElementById(this._addUID("GPopacityValue_ID_" + layerID)); + opacityId.innerHTML = opacityValue + "%"; + globe.setLayerOpacity(layerID, opacityValue / 100); +}; + +/** + * Updates picto opacity value on layer opacity change + * + * @method _updateLayerOpacity + * @param {String} layerId - layer id + * @param {Number} opacity - opacity value + * @private + */ +LayerSwitcher.prototype._updateLayerOpacity = function (layerId, opacity) { + if (opacity > 1) { + opacity = 1; + } + if (opacity < 0) { + opacity = 0; + } + + var layerOpacityInput = document.getElementById(this._addUID("GPopacityValueDiv_ID_" + layerId)); + if (layerOpacityInput) { + layerOpacityInput.value = Math.round(opacity * 100); + } + + var layerOpacitySpan = document.getElementById(this._addUID("GPopacityValue_ID_" + layerId)); + if (layerOpacitySpan) { + layerOpacitySpan.innerHTML = Math.round(opacity * 100) + "%"; + } +}; + +/** + * Changes layer visibility on layer visibility picto click + * + * @method _onVisibilityLayerClick + * @param {Object} e - HTML event + * @private + */ +LayerSwitcher.prototype._onVisibilityLayerClick = function (e) { + var globe = this.getGlobe(); + + var layerID = this._resolveLayerId(e.target.id); + globe.setLayerVisibility(layerID, e.target.checked); // update viewer +}; + +/** + * Changes picto visibility on layer visibility change + * + * @method _updateLayerVisibility + * @param {String} layerId - layer id + * @param {Boolean} visibility - visible if true + * @private + */ +LayerSwitcher.prototype._updateLayerVisibility = function (layerId, visibility) { + var layerVisibilityInput = document.getElementById(this._addUID("GPvisibility_ID_" + layerId)); + if (layerVisibilityInput) { + layerVisibilityInput.checked = visibility; + } +}; + +/** + * Opens layer information panel on picto click + * + * @method _onOpenLayerInfoClick + * @param {Event} e - MouseEvent + * @private + */ +LayerSwitcher.prototype._onOpenLayerInfoClick = function (e) { + var layerID = this._resolveLayerId(e.target.id); + + var layerOptions = this._layers[layerID]; + + var panel; + var info; + + // Close layer info panel + var divId = document.getElementById(e.target.id); + if (divId.className === "GPlayerInfoOpened") { + if (divId.classList !== undefined) { + divId.classList.remove("GPlayerInfoOpened"); + divId.classList.add("GPlayerInfo"); + } + + panel = document.getElementById(this._addUID("GPlayerInfoPanel")); + if (panel.classList !== undefined) { + panel.classList.remove("GPpanel"); + panel.classList.remove("GPlayerInfoPanelOpened"); + panel.classList.add("GPlayerInfoPanelClosed"); + } + + info = document.getElementById(this._addUID("GPlayerInfoContent")); + panel.removeChild(info); + return; + } + + var layers = document.getElementsByClassName("GPlayerInfoOpened"); + for (var i = 0; i < layers.length; i++) { + layers[i].className = "GPlayerInfo"; + } + + // Open layer info panel + if (divId.classList !== undefined) { + divId.classList.remove("GPlayerInfo"); + divId.classList.add("GPlayerInfoOpened"); + } + + panel = document.getElementById(this._addUID("GPlayerInfoPanel")); + if (panel.classList !== undefined) { + panel.classList.add("GPpanel"); + panel.classList.remove("GPlayerInfoPanelClosed"); + panel.classList.add("GPlayerInfoPanelOpened"); + } + + info = document.getElementById(this._addUID("GPlayerInfoContent")); + if (info) { + panel.removeChild(info); + } + + // on récupère les infos associées au layer pour mettre dynamiquement le contenu du panel d'informations + var obj = { + title : layerOptions.title, + description : layerOptions.description, + quicklookUrl : layerOptions.quicklookUrl, + metadata : layerOptions.metadata, + legends : layerOptions.legends + }; + + var infoLayer = this._createContainerLayerInfoElement(obj); + panel.appendChild(infoLayer); +}; + +/** + * removes layer from layer switcher and globe on picto click + * + * @method _onDropLayerClick + * @param {Event} e - MouseEvent + * @private + */ +LayerSwitcher.prototype._onDropLayerClick = function (e) { + var globe = this.getGlobe(); + + var layerID = this._resolveLayerId(e.target.id); + // removing the layer will trigger the event listener + // which will call this.removeLayer and delete the div + globe.removeLayer(layerID); + + this._updateLayerListContainer(); +}; + +/** + * changes layers order on drag and drop + * + * @method _onDropLayerClick + * @param {Event} e - HTML event + * @private + */ +LayerSwitcher.prototype._onDragAndDropLayerClick = function (e) { + var globe = this.getGlobe(); + + // Handling of the indexes : gives the little indexes (lowest layers) to the non-visible layers (displayed: false) + // when the index of a visible layer changes. + // Always moves the non-visible layers under the other layers (to not hide them) + + if (e.newIndex - e.oldIndex === 0) { + return; + } + + var targetIndex = null; + if (!e.newIndex || e.newIndex === 0) { + targetIndex = globe.getColorLayers().length - 1; + } else { + var layerTargetID = this._resolveLayerId(e.from.childNodes[e.newIndex + (e.newIndex - e.oldIndex < 0 ? 1 : -1)].id); + targetIndex = globe.getLayerById(layerTargetID).sequence; + } + + var layerID = this._resolveLayerId(e.item.id); + + globe.moveLayerToIndex(layerID, targetIndex); +}; + +/** + * Checks layers range + * + * @method _inRangeUpdate + * @param {Array} layersDisplayed - list of displayed layers id + * @private + */ +LayerSwitcher.prototype._inRangeUpdate = function (layersDisplayed) { + for (var layerKey in this._layers) { + var layer = this._layers[layerKey]; + if (!layer) { + continue; + } + // Check if layer is displayed. + var layerDiv; + var bInRange = layersDisplayed.indexOf(layer.id) >= 0; + if (bInRange && !layer.inRange) { + layer.inRange = true; + layerDiv = document.getElementById(this._addUID("GPlayerSwitcher_ID_" + layer.id)); + layerDiv.classList.remove("outOfRange"); + } else if (!bInRange && layer.inRange) { + layer.inRange = false; + layerDiv = document.getElementById(this._addUID("GPlayerSwitcher_ID_" + layer.id)); + layerDiv.classList.add("outOfRange"); + } + } +}; + +/** + * Update the layer list container + * + * @method _updateLayerListContainer + * @private + */ +LayerSwitcher.prototype._updateLayerListContainer = function () { + if (this._layerListContainer) { + var globe = this.getGlobe(); + + // empty the previous container + while (this._layerListContainer.firstChild) { + this._layerListContainer.removeChild(this._layerListContainer.firstChild); + } + // reorders layers according to the layer stack (globe.getLayers returns an reverse ordenered array).. + var layers = globe.getColorLayers(); + var orderedLayers = layers.sort(function (a, b) { + return b.sequence - a.sequence; + }); + // ... and adds the correct div to the different layers, in the zindex decreasing order + for (var j = 0; j < orderedLayers.length; j++) { + if (!this._layers[orderedLayers[j].id]) { + continue; + } + // retrieves the div of the layer, stored in the _layers array + var layerDiv = this._layers[orderedLayers[j].id].div; + this._layerListContainer.appendChild(layerDiv); + } + } else { + logger.error("[Itowns.control.LayerSwitcher] _updateLayerListContainer : layer list container not found to update layers order ?!"); + } +}; + +// ################################################################### // +// ############################ Utils ################################ // +// ################################################################### // + +/** + * Gets layer informations : title, description, quicklookurl, legends, metadata + * + * @private + * @memberof LayerSwitcher + * @method _getLayerInfo + * @param {Object} layer - the layer object + * @returns {Object} layerInfo - layer informations + */ +LayerSwitcher.prototype._getLayerInfo = function (layer) { + var layerInfo = {}; + if (layer) { + layerInfo._title = layer.title || null; + layerInfo._description = layer.description || null; + layerInfo._quicklookUrl = layer.quicklookUrl || null; + layerInfo._metadata = layer.metadata || null; + layerInfo._legends = layer.legends || null; + } + return layerInfo; +}; + +/** + * Gets layer id from div id + * + * @method _resolveLayerId + * @param {String} divId - HTML div id + * @returns {String} layer id + * @private + */ +LayerSwitcher.prototype._resolveLayerId = function (divId) { + var divName = SelectorID.name(divId); // ex GPvisibilityPicto_ID_26 + return divName.substring(divName.indexOf("_ID_") + 4); // ex. 26 +}; + +export default LayerSwitcher; diff --git a/src/Itowns-review/Controls/MiniGlobe.js b/src/Itowns-review/Controls/MiniGlobe.js new file mode 100644 index 000000000..8c4c21ac8 --- /dev/null +++ b/src/Itowns-review/Controls/MiniGlobe.js @@ -0,0 +1,161 @@ +import GlobeViewExtended from "../GlobeViewExtended"; +import Utils from "../../Common/Utils"; +import SelectorID from "../../Common/Utils/SelectorID"; +import MiniGlobeDOM from "../../Common/Controls/MiniGlobeDOM"; +import Widget from "./Widget"; + +/** + * @classdesc + * Control to display the MiniGlobe with itowns + * + * @constructor + * @extends {itowns.control.Widget} + * @alias itowns.control.MiniGlobe + * @param {Object} [options] - control options + * @param {Object} [options.layer] - custom itowns layer to display on the mini globe + * @example + * var miniglobe = new itowns.control.MiniGlobe(); + * + */ +function MiniGlobe (options) { + options = options || {}; + + if (!(this instanceof MiniGlobe)) { + throw new TypeError("ERROR CLASS_CONSTRUCTOR"); + } + + if (options && typeof options !== "object") { + throw new Error("ERROR WRONG_TYPE : options should be an object"); + } + + this._initialize(); + + var container = this._initContainer(); + this._options = options; + + Widget.call( + this, { + name : "Overview", + element : container, + target : options.target, + position : options.position + } + ); +} + +/* + * @lends module:MiniGlobe + */ +MiniGlobe.prototype = Object.create(Widget.prototype, {}); + +// retrieves methods of the common class MiniGlobeDOM +Utils.assign(MiniGlobe.prototype, MiniGlobeDOM); + +/** + * Constructor (alias) + * + * @private + */ +MiniGlobe.prototype.constructor = MiniGlobe; + +// ################################################################### // +// ############## public methods (getters, setters) ################## // +// ################################################################### // + +/** + * Bind globe to control + * + * @param {GlobeViewExtended} globe - the globe + */ +MiniGlobe.prototype.setGlobe = function (globe) { + // info : this function is called after a globe.addWidget() or a globe.removeWidget() + + if (globe) { // In the case of the adding of a control to the globe + var minDistance = 6650000; + var maxDistance = 30000000; + var positionOnGlobe = globe.getCenter(); + var miniView = new GlobeViewExtended(this._element, positionOnGlobe, { + // `limit globe' subdivision level: + // we're don't need a precise globe model + // since the mini globe will always be seen from a far point of view (see minDistance above) + maxSubdivisionLevel : 6, + sseSubdivisionThreshold : 3, + // Don't instance default controls since miniview's camera will be synced + // on the main view's one (see globeView.onAfterRender) + noControls : true + }); + + miniView.setBackground(); + + var updateMiniGlobeHandler = function () { + // clamp distance camera from globe + var distanceCamera = globe.getGlobeView().camera.camera3D.position.length(); + var distance = Math.min(Math.max(distanceCamera, minDistance), maxDistance); + var camera = miniView.getGlobeView().camera.camera3D; + var cameraTargetPosition = globe.getGlobeView().controls.getCameraTargetPosition(); + // Update target miniview's camera + camera.position.copy(cameraTargetPosition).setLength(distance); + camera.lookAt(cameraTargetPosition); + miniView.notifyChange(camera); + }; + globe.listen(GlobeViewExtended.EVENTS.AFTER_RENDER, updateMiniGlobeHandler); + if (globe.isInitialized()) { + updateMiniGlobeHandler(); + } else { + globe.listen(GlobeViewExtended.EVENTS.GLOBE_INITIALIZED, updateMiniGlobeHandler); + } + + /** + * Add one imagery layer to the miniview (by default, the ortho) + */ + var miniGlobeLayer = this._options.layer; + miniView.addLayer(miniGlobeLayer); + // save as property of the control the globe created for the overview + this._globeObj = miniView; + } else if (globe == null) { + // if globe == null we remove the overview control + // we delete the overview control DOM + while (this.getElement().hasChildNodes()) { + this.getElement().removeChild(this.getElement().lastChild); + } + this.getElement().parentNode.removeChild(this.getElement()); + } + + // call original setGlobe method + Widget.prototype.setGlobe.call(this, globe); +}; + +// ################################################################### // +// ##################### init component ############################## // +// ################################################################### // + +/** + * Initialize MiniGlobe control (called by constructor) + * + * @private + */ +MiniGlobe.prototype._initialize = function () { + // id of the widget : usefull to suffix the CSS ids (to handle cases with several widgets on the same page) + this._uid = SelectorID.generate(); + + // div which will contain the list divs. + this._MiniGlobeContainer = null; + + // callbacks + this._callbacks = {}; +}; + +/** + * Creates control main container + * + * @method _initContainer + * @returns {DOMElement} container - widget container + * @private + */ +MiniGlobe.prototype._initContainer = function () { + var container = this._createMainContainerElement(); + + return container; +}; + +export default MiniGlobe; diff --git a/src/Itowns-review/Controls/MousePosition.js b/src/Itowns-review/Controls/MousePosition.js new file mode 100644 index 000000000..9a96a292e --- /dev/null +++ b/src/Itowns-review/Controls/MousePosition.js @@ -0,0 +1,1278 @@ +import proj4 from "proj4"; +import Logger from "../../Common/Utils/LoggerByDefault"; +import Gp from "geoportal-access-lib"; +import GlobeViewExtended from "../GlobeViewExtended"; +import Utils from "../../Common/Utils"; +import RightManagement from "../../Common/Utils/CheckRightManagement"; +import SelectorID from "../../Common/Utils/SelectorID"; +import MousePositionDOM from "../../Common/Controls/MousePositionDOM"; +import Widget from "./Widget"; +import PositionFormater from "./Utils/PositionFormater"; +import CRS from "../CRS/CRS"; + +var logger = Logger.getLogger("MousePosition"); + +/** + * @classdesc + * + * MousePosition Control. + * + * @constructor + * @alias itowns.control.MousePosition + * @extends {itowns.control.Control} + * @param {Object} options - options for function call. + * @param {Boolean} [options.ssl = true] - use of ssl or not (default true, service requested using https protocol) + * @param {Boolean} [options.collapsed = true] - Specify if MousePosition control should be collapsed at startup. Default is true. + * @param {Array} [options.systems] - list of projection systems, default are Geographical ("EPSG:4326"), Web Mercator ("EPSG:3857"), Lambert 93 ("EPSG:2154") and extended Lambert 2 ("EPSG:27572"). + * Each array element (=system) is an object with following properties : + * @param {String} options.systems.crs - Proj4 crs alias (from proj4 defs). e.g. : "EPSG:4326". Required + * @param {String} [options.systems.label] - CRS label to be displayed in control. Default is crs code (e.g. "EPSG:4326") + * @param {String} options.systems.type - CRS units type for coordinates conversion : "Geographical" or "Metric". Default: "Metric" + * @param {Object} [options.systems.geoBBox] - Aera covered by the system (WGS84 coordinates). + * @param {Number} options.systems.geoBBox.right - Right bound. + * @param {Number} options.systems.geoBBox.left - Left bound. + * @param {Number} options.systems.geoBBox.top - Top bound. + * @param {Number} options.systems.geoBBox.bottom - Bottom bound. + * @param {Array} [options.units] - list of coordinates units, to be displayed in control units list. + * Values may be "DEC" (decimal degrees), "DMS" (sexagecimal), "RAD" (radians) and "GON" (grades) for geographical coordinates, + * and "M" or "KM" for metric coordinates + * @param {Array} [options.displayAltitude = true] - activate (true) or deactivate (false) the altitude panel. True by default + * @param {Array} [options.displayCoordinates = true] - activate (true) or deactivate (false) the coordinates panel. True by default + * @param {Object} [options.altitude] - elevation configuration + * @param {Object} [options.altitude.serviceOptions] - options of elevation service + * @param {Number} [options.altitude.responseDelay] - latency for altitude request, 500 ms by default + * @param {Number} [options.altitude.triggerDelay] - immobilisation time of movement on the globe to trigger the elevation calculation, 200 ms by default + * @example + * var mousePosition = new itowns.control.MousePosition({ + * collapsed : false, + * displayCoordinates : true, + * displayAltitude : true, + * altitude : { + * triggerDelay : 100, + * responseDelay : 500, + * serviceOptions : {} + * }, + * systems : [ + * { + * crs : "EPSG:3857", + * label : "Mercator", + * type : "Metric" + * }, + * { + * crs : "EPSG:32620", + * label : "UTM 20N (Guadeloupe, Martinique)", + * type : "Metric", + * geoBBox : { + * left: -66.00, + * bottom : 0.00, + * right : -60.00, + * top : 84.00 + * } + * } + * ], + * units : ["DEC", "DMS"] + * }); + */ +function MousePosition (options) { + options = options || {}; + + if (!(this instanceof MousePosition)) { + throw new TypeError("ERROR CLASS_CONSTRUCTOR"); + } + + if (options && typeof options !== "object") { + throw new Error("ERROR WRONG_TYPE : options should be an object"); + } + + this._initialize(options); + + this._callbacks = {}; + + // init control DOM container + var container = this._initContainer(options); + + Widget.call( + this, { + name : "MousePosition", + element : container, + target : options.target, + position : options.position + } + ); +}; + +/** + * @lends module:MousePosition + */ +MousePosition.prototype = Object.create(Widget.prototype, {}); + +Utils.assign(MousePosition.prototype, MousePositionDOM); + +/** + * Constructor (alias) + */ +MousePosition.prototype.constructor = MousePosition; + +/** + * Bind globe to control + * + * @param {GlobeViewExtended} globe - the globe + */ +MousePosition.prototype.setGlobe = function (globe) { + if (globe) { // In the case of the adding of a control to the globe + this._centerElement = this._createMapCenter(); + globe.getTargetElement().appendChild(this._centerElement); + + // defines the callback on the map to retrieve the coordinates + this._callbacks.mouseMove = this.onMouseMove.bind(this); + + // valid event for desktop mode + if (!this.collapsed) { + if (this._isDesktop) { + globe.listen(GlobeViewExtended.EVENTS.MOUSE_MOVE, this._callbacks.mouseMove); + } else { + globe.listen(GlobeViewExtended.EVENTS.CENTER_CHANGED, this.onGlobeMove); + } + } + } else if (globe == null) { // if globe == null we remove the MP control + // deletes the listener associated to the mousePosition control + this._globe.forget(GlobeViewExtended.EVENTS.MOUSE_MOVE, this._callbacks.mouseMove); + // deletes the mousePosition control DOM + while (this.getElement().hasChildNodes()) { + this.getElement().removeChild(this.getElement().lastChild); + } + this.getElement().parentNode.removeChild(this.getElement()); + this._globe.getTargetElement().removeChild(this._centerElement); + } + // call original setGlobe method + Widget.prototype.setGlobe.call(this, globe); +}; + +// ################################################################### // +// #################### user interface methods ####################### // +// ################################################################### // + +/** + * Sets additional projection system + * + * @param {Object} system - Projection system defined in the Itowns/CRS/CRS.js class + * @param {String} system.crs - Proj4 crs alias (from proj4 defs) e.g. "EPSG:4326" + * @param {String} [system.label] - CRS label to be displayed in control. Default is system.crs alias + * @param {String} [system.type] - CRS units type for coordinates conversion (one of control options.units). Default is "Metric" + */ +MousePosition.prototype.addSystem = function (system) { + if (typeof system !== "object") { + logger.error("MousePosition:addSystem - system parameter should be an object"); + return; + } + if (!system.crs) { + logger.error("crs not defined !"); + return; + } + if (!system.label) { + logger.warn("crs label not defined, use crs code by default."); + system.label = system.crs; + } + if (!system.type) { + logger.warn("type srs not defined, use 'Metric' by default."); + system.type = "Metric"; + } + + // 1. adds system to control systems + for (var j = 0; j < this._projectionSystems.length; j++) { + var obj = this._projectionSystems[j]; + if (system.crs === obj.crs) { + // warn user + logger.warn("crs '{}' already configured", obj.crs); + } + } + + system.code = this._projectionSystems.length; + this._projectionSystems.push(system); + + // 2. adds system settings option to container (if it was already build) + var selectSystem = document.getElementById(this._addUID("GPmousePositionProjectionSystem")); + if (selectSystem) { + var option = document.createElement("option"); + option.value = system.code; + option.text = system.label; + selectSystem.appendChild(option); + } +}; + +/** + * Sets additional projection systems + * + * @param {Array} systems - Array of system object, with following properties : + * @param {String} systems.crs - Proj4 CRS alias (from proj4 defs) e.g. "EPSG:4326" + * @param {String} systems.label - CRS label (for coordinates conversion) + * @param {String} systems.type - CRS units type to be displayed in control (one of control options.units). Default is "Metric" + */ +MousePosition.prototype.addSystems = function (systems) { + if (!systems) { + return; + } + if (!Array.isArray(systems)) { + logger.error("MousePosition:addSystems - systems parameter should be an array"); + return; + } + for (var i = 0; i < systems.length; i++) { + this.addSystem(systems[i]); + } +}; + +/** + * Removes projection system (in case there are several system with same code, only the first one will be removed) + * + * @param {String} systemCrs - CRS alias (from proj4 defs) + */ +MousePosition.prototype.removeSystem = function (systemCrs) { + if (!systemCrs || typeof systemCrs !== "string") { + logger.error("MousePosition:removeSystem - systemCode parameter should be a string"); + return; + } + + var systemCode = null; + // finds system in control projection systems list + for (var i = 0; i < this._projectionSystems.length; i++) { + var proj = this._projectionSystems[i]; + if (systemCrs === proj.crs) { + systemCode = proj.code; + // removes system from control projection systems list + this._projectionSystems.splice(i, 1); + break; + } + } + + if (systemCode == null) { + logger.warn("MousePosition:removeSystem - system not found"); + return; + } + + // re-initialization of codes + var oldNewCodeGlobe = []; + for (var ii = 0; ii < this._projectionSystems.length; ii++) { + oldNewCodeGlobe[Number(this._projectionSystems[ii].code)] = ii; + this._projectionSystems[ii].code = ii; + } + + // finds system in control container systems list + var indexChildToRemove = null; + var systemList = document.getElementById(this._addUID("GPmousePositionProjectionSystem")); + for (var j = 0; j < systemList.childNodes.length; j++) { + if (systemCode === systemList.childNodes[j].value) { + indexChildToRemove = j; + continue; + } + systemList.childNodes[j].value = oldNewCodeGlobe[Number(systemList.childNodes[j].value)]; + } + // removes system from control container systems list + if (indexChildToRemove != null) { + systemList.removeChild(systemList.childNodes[indexChildToRemove]); + } + + // choose arbitrarily a new current system if needed + if (this._currentProjectionSystems.code === systemCode) { + systemList.childNodes[0].setAttribute("selected", "selected"); + this._setCurrentSystem(systemList.childNodes[0].value); + } +}; + +/** + * Sets control units (to be displayed) + * + * @param {Array} units - list of all coordinates units, to be displayed in control units list. + * Values may be "DEC" (decimal degrees), "DMS" (sexagecimal), "RAD" (radians) and "GON" (grades) for geographical coordinates, + * and "M" or "KM" for metric coordinates + */ +MousePosition.prototype.setUnits = function (units) { + if (!units || !Array.isArray(units)) { + return; + } + this.options.units = units; + this._projectionUnits = {}; + this._initProjectionUnits(); + if (this._currentProjectionType) { + this._setTypeUnitsPanel(this._currentProjectionType); + } +}; + +/** + * Sets control altitude options (useless if displayAltitude == false) + * + * @param {Object} options - altitude options + * @param {Object} [options.serviceOptions] - options of elevation service + * @param {Number} [options.responseDelay] - latency for elevation request, 500 ms by default + * @param {Number} [options.triggerDelay] - immobilisation time of movement on the globe to trigger the elevation calculation, 200 ms by default + */ +MousePosition.prototype.setAltitudeOptions = function (options) { + if (!options || typeof options !== "object") { + return; + } + this.options.altitude.triggerDelay = options.triggerDelay; + this.options.altitude.responseDelay = options.responseDelay; + if (options.serviceOptions) { + for (var opt in options.serviceOptions) { + if (options.serviceOptions.hasOwnProperty(opt)) { + this.options.altitude.serviceOptions[opt] = options.serviceOptions[opt]; + } + } + } +}; + +/** + * Displays or hides elevation panel + * + * @param {Boolean} displayAltitude - true to display elevation panel, false to hide it + */ +MousePosition.prototype.displayAltitude = function (displayAltitude) { + if (displayAltitude === undefined) { + return; + } + if (typeof this._noRightManagement === "undefined") { + this._checkRightsManagement(); + } + this.options.displayAltitude = displayAltitude; + this._setElevationPanel(displayAltitude); +}; + +/** + * Displays or hides coordinates panel + * + * @param {Boolean} displayCoordinates - true to display coordinates panel, false to hide it + */ +MousePosition.prototype.displayCoordinates = function (displayCoordinates) { + if (displayCoordinates === undefined) { + return; + } + this.options.displayCoordinates = displayCoordinates; + this._setCoordinatesPanel(displayCoordinates); + this._setSettingsPanel(displayCoordinates); +}; + +/** + * Collapses or displays control main container + * + * @param {Boolean} collapsed - True to collapse control, False to display it + */ +MousePosition.prototype.setCollapsed = function (collapsed) { + if (collapsed === undefined) { + logger.error("MousePosition:setCollapsed - missing collapsed parameter"); + return; + } + if ((collapsed && this.collapsed) || (!collapsed && !this.collapsed)) { + return; + } + if (!this._isDesktop) { + document.getElementById(this._addUID("GPmapCenter")).className = collapsed ? "" : "GPmapCenterVisible"; + } + // simulates the opening of the panel after a click + this.onShowMousePositionClick(); + this._showMousePositionContainer.checked = !collapsed; +}; + +// ################################################################### // +// ######################## initialize control ####################### // +// ################################################################### // + +/** + * Initializes control (called by MousePosition constructor) + * + * @method _initialize + * @param {Object} options - control options (set by user) + * @private + */ +MousePosition.prototype._initialize = function (options) { + // Set default options + // {Object} control options - set by user or by default + this.options = options || {}; + this.options.collapsed = (options.collapsed !== undefined) ? options.collapsed : true; + /** {Boolean} specify if MousePosition control is collapsed (true) or not (false) */ + this.collapsed = this.options.collapsed; + this.options.units = options.units || []; + this.options.displayAltitude = (options.displayAltitude !== undefined) ? options.displayAltitude : true; + this.options.displayCoordinates = (options.displayCoordinates !== undefined) ? options.displayCoordinates : true; + this.options.systems = options.systems || []; + if (options.altitude) { + var altitude = options.altitude; + this.options.altitude = { + triggerDelay : (altitude.triggerDelay !== undefined) ? altitude.triggerDelay : 200, + responseDelay : (altitude.responseDelay !== undefined) ? altitude.responseDelay : 500, + serviceOptions : altitude.serviceOptions || {}, + noDataValue : (altitude.noDataValue !== undefined) ? altitude.noDataValue : -99999, + noDataValueTolerance : (altitude.noDataValueTolerance !== undefined) ? altitude.noDataValueTolerance : 90000 + }; + } else { + this.options.altitude = { + triggerDelay : 200, + responseDelay : 500, + serviceOptions : {} + }; + } + + // id of the widget : usefull to suffix the CSS ids (to handle cases with several widgets on the same page) + this._uid = SelectorID.generate(); + + // initialization of the projections systems + this._projectionSystems = []; + this._initProjectionSystems(); + + // initialization of the units systems + this._projectionUnits = {}; + this._initProjectionUnits(); + + // support detect : desktop or tactile + this._isDesktop = Utils.detectSupport(); + + // implements a timer threshold + if (this.options.altitude.triggerDelay < 100) { + this.options.altitude.triggerDelay = 100; + } + + // {Number} timer on movestopped delay (altitude calculation) + this._timer = this.options.altitude.triggerDelay; + + // {Object} Selected projection system + this._currentProjectionSystems = this._projectionSystems[0]; + + // {String} Selected projection units typs : Geographical or metric + this._currentProjectionType = this._projectionSystems[0].type; + + // {String} Selected projection unit + this._currentProjectionUnits = this._projectionUnits[this._currentProjectionType][0].code; + + // {Object} Projection units container (DOM Element) + this._projectionUnitsContainer = null; + + // {Object} control panel container (DOM Element) + this._showMousePositionContainer = null; + + // management of the altitude panel display + if (!this.options.displayAltitude && !this.options.displayCoordinates) { + // reactivate the display of coordinates, to not display an empty panel + this.options.displayCoordinates = true; + } + + // rights management on resources and services + // if we want an altitude calculation, we check the alti resources rights... + if (this.options.displayAltitude) { + this._checkRightsManagement(); + } +}; + +/** + * this method is called by the constructor and initialize the projection + * systems. + * getting coordinates in the requested projection : + * see this.onMousePositionProjectionSystemChange() + * + * @method _initProjectionSystems + * @private + */ +MousePosition.prototype._initProjectionSystems = function () { + // user has the possibility to modify the list of systems to display + // Ex. this.options.systems + + // available projection systems vy default + var projectionSystemsByDefault = [{ + label : "Géographique", + crs : "EPSG:4326", + type : "Geographical" + }, { + label : "Mercator", + crs : "EPSG:3857", + type : "Metric" + }, { + label : "Lambert 93", + crs : "EPSG:2154", + type : "Metric", + geoBBox : { + left : -9.86, + bottom : 41.15, + right : 10.38, + top : 51.56 + } + }, { + label : "Lambert II étendu", + crs : "EPSG:27572", + type : "Metric", + geoBBox : { + left : -4.87, + bottom : 42.33, + right : 8.23, + top : 51.14 + } + }]; + + var systems = this.options.systems; + for (var i = 0; i < systems.length; i++) { + // definition of a reference system + var sys = systems[i]; + this.addSystem(sys); + } + + if (this._projectionSystems.length === 0) { + // we add the default projection systems + for (var ii = 0; ii < projectionSystemsByDefault.length; ii++) { + this.addSystem(projectionSystemsByDefault[ii]); + } + } +}; + +/** + * this method is called by the constructor and initialize the units. + * getting coordinates in the requested units : + * see this.onMousePositionProjectionUnitsChange() + * + * @method _initProjectionUnits + * @private + */ +MousePosition.prototype._initProjectionUnits = function () { + // user has the possibility to modify the list of units to display + // Ex. + // this.options.units : ["DEC", "DMS"] + + // available units systems by default + var projectionUnitsByDefault = { + Geographical : [{ + code : "DEC", + label : "degrés décimaux", + convert : this._displayDEC + }, { + code : "DMS", + label : "degrés sexagésimaux", + convert : this._displayDMS + }, { + code : "RAD", + label : "radians", + convert : this._displayRAD + }, { + code : "GON", + label : "grades", + convert : this._displayGON + }], + Metric : [{ + code : "M", + label : "mètres", + convert : this._displayMeter + }, { + code : "KM", + label : "kilomètres", + convert : this._displayKMeter + }] + }; + + var units = this.options.units; + + for (var type in projectionUnitsByDefault) { + if (projectionUnitsByDefault.hasOwnProperty(type)) { + var found = false; + for (var j = 0; j < projectionUnitsByDefault[type].length; j++) { + var obj = projectionUnitsByDefault[type][j]; + for (var i = 0; i < units.length; i++) { + var unit = units[i]; + if (obj.code === unit) { + found = true; + if (!this._projectionUnits[type]) { + this._projectionUnits[type] = []; + } + this._projectionUnits[type].push(obj); + } + } + } + if (!found) { + this._projectionUnits[type] = projectionUnitsByDefault[type]; + } + } + } + + // in case of... + if (typeof this._projectionUnits === "object" && Object.keys(this._projectionUnits).length === 0) { + this._projectionUnits = projectionUnitsByDefault; + } +}; + +/** + * this method is called by constructor + * and check the rights to resources + * + * @method _checkRightsManagement + * @private + */ +MousePosition.prototype._checkRightsManagement = function () { + var rightManagement = RightManagement.check({ + key : this.options.apiKey, + resources : ["SERVICE_CALCUL_ALTIMETRIQUE_RSC"], + services : ["Elevation"] + }); + + this._noRightManagement = !rightManagement; + + // retrieves the usefull infos + // on this control, we do not care about the ressource bescause it is unique + // Ex : the API key from the autoconfiguration if it has not been given + if (!this.options.apiKey) { + this.options.apiKey = rightManagement.key; + } +}; + +// ################################################################### // +// ######################## methods handle dom ####################### // +// ################################################################### // + +/** + * Create control main container (called by MousePosition constructor) + * + * @method _initContainer + * @param {Object} options - options + * @param {Boolean} options.collapsed - Specify if MousePosition control should be collapsed + * @param {Array} options.displayAltitude - activate (true) or deactivate (false) the altitude panel + * @param {Array} options.displayCoordinates - activate (true) or deactivate (false) the coordinates panel + * @returns {DOMElement} container - widget container + * @private + */ +MousePosition.prototype._initContainer = function (options) { + // creates the main container + var container = this._createMainContainerElement(); + + var inputShow = this._showMousePositionContainer = this._createShowMousePositionElement(); + if (!options.collapsed) { + inputShow.checked = "checked"; + } + container.appendChild(inputShow); + + var picto = this._createShowMousePositionPictoElement(this._isDesktop); + container.appendChild(picto); + + var panel = this._createMousePositionPanelElement(); + + var header = this._createMousePositionPanelHeaderElement(); + panel.appendChild(header); + + var basic = this._createMousePositionPanelBasicElement( + options.displayAltitude, + options.displayCoordinates + ); + panel.appendChild(basic); + + var arraySettings = this._createShowMousePositionSettingsElement(options.displayCoordinates); + for (var j = 0; j < arraySettings.length; j++) { + panel.appendChild(arraySettings[j]); + } + + var settings = this._createMousePositionSettingsElement(options.displayCoordinates); + var systems = this._projectionSystemsContainer = this._createMousePositionSettingsSystemsElement(this._projectionSystems); + var units = this._projectionUnitsContainer = this._createMousePositionSettingsUnitsElement(this._projectionUnits[this._currentProjectionType]); + + settings.appendChild(systems); + settings.appendChild(units); + panel.appendChild(settings); + container.appendChild(panel); + + return container; +}; + +/** + * this method is called by this.() + * and it changes the elevation view panel into the dom. + * + * @method _setElevationPanel + * @param {Boolean} active - true:active, false:disable + * @private + */ +MousePosition.prototype._setElevationPanel = function (active) { + var div = null; + + if (!active) { + div = document.getElementById("GPmousePositionAltitude-" + this._uid); + div.style.display = "none"; + } else { + if (this._noRightManagement) { + div = document.getElementById("GPmousePositionAlt-" + this._uid); + div.innerHTML = "No rights!"; + } else { + div = document.getElementById("GPmousePositionAltitude-" + this._uid); + div.style.display = ""; + } + } +}; + +/** + * this method is called by this.() + * and it changes the coordinate view panel into the dom. + * + * @method _setCoordinatesPanel + * @param {Boolean} active - true:active, false:disable + * @private + */ +MousePosition.prototype._setCoordinatesPanel = function (active) { + var div = document.getElementById("GPmousePositionCoordinate-" + this._uid); + if (!active) { + div.style.display = "none"; + } else { + div.style.display = ""; + } +}; + +/** + * this method is called by this.() + * and it changes the settings view panel into the dom. + * + * @method _setSettingsPanel + * @param {Boolean} active - true:active, false:disable + * @private + */ +MousePosition.prototype._setSettingsPanel = function (active) { + var divPicto = document.getElementById("GPshowMousePositionSettingsPicto-" + this._uid); + var divPanel = document.getElementById("GPmousePositionSettings-" + this._uid); + if (!active) { + divPicto.style.display = "none"; + divPanel.style.display = "none"; + } else { + divPicto.style.display = ""; + divPanel.style.display = ""; + } +}; + +/** + * this method is called by this.onMousePositionProjectionSystemChange() + * when changes to a metric or a geographical units. + * + * @method _setTypeUnitsPanel + * @param {String} type - Geographical or Metric + * @private + */ +MousePosition.prototype._setTypeUnitsPanel = function (type) { + var container = this._projectionUnitsContainer; + + // deletes the childNodes + while (container.firstChild) { + container.removeChild(container.firstChild); + } + + var units = this._projectionUnits[type]; + for (var j = 0; j < units.length; j++) { + var obj = units[j]; + var option = document.createElement("option"); + option.value = (obj.code) ? obj.code : j; + option.text = obj.label || j; + // option.label = obj.label; + container.appendChild(option); + } + + // the new type of system + this._currentProjectionType = type; + // as the system changed, the unit system has to change too ! + this._currentProjectionUnits = this._projectionUnits[type][0].code; +}; + +// ################################################################### // +// ######################## method units convert ##################### // +// ################################################################### // + +/** + * degreedecimal + * + * @method _displayDEC + * @param {Object} coords - coordinatesobject {lon, lat} + * @return {Object} coordinate - coordinate object : {lat : 48, lng : 2} par exemple + * @private + */ +MousePosition.prototype._displayDEC = function (coords) { + var coordinate = {}; + coordinate.lat = PositionFormater.roundToDecimal(coords.lat, 6); + coordinate.lng = PositionFormater.roundToDecimal(coords.lon, 6); + return coordinate; +}; + +/** + * degreedecimal2sexagecimal + * + * @method _displayDMS + * @param {Object} coords - coordinates object {lon, lat} + * @return {Object} coordinate - coordinate object : {lng : "2° 00′ 00″ E", lat : "48° 00′ 00″ N"} par exemple + * @private + */ +MousePosition.prototype._displayDMS = function (coords) { + var coordinate = {}; + coordinate.lat = PositionFormater.decimalLatToDMS(coords.lat); + coordinate.lng = PositionFormater.decimalLongToDMS(coords.lon); + return coordinate; +}; + +/** + * degreedecimal2radian + * + * @method _displayRAD + * @param {Object} coords - coordinates object {lon, lat} + * @return {Object} coordinate - coordinate object : {lat : "0.02837864", lng : "0.84300269"} par exemple + * @private + */ +MousePosition.prototype._displayRAD = function (coords) { + var coordinate = {}; + coordinate.lat = PositionFormater.decimalToRadian(coords.lat); + coordinate.lng = PositionFormater.decimalToRadian(coords.lon); + return coordinate; +}; + +/** + * degreedecimal2grade + * + * @method _displayGON + * @param {Object} coords - coordinates object {lon, lat} + * @return {Object} coordinate - coordinate object : {lat : "4.09545898", lng : "53.68751528"} par exemple + * @private + */ +MousePosition.prototype._displayGON = function (coords) { + var coordinate = {}; + coordinate.lat = PositionFormater.decimalToGrade(coords.lat); + coordinate.lng = PositionFormater.decimalToGrade(coords.lon); + return coordinate; +}; + +/** + * meter + * + * @method _displayMeter + * @param {Object} coords - coords object {lon, lat} + * @return {Object} coordinate - coordinate object : {x : "148593.58", y : "6176560.95"} par exemple + * @private + */ +MousePosition.prototype._displayMeter = function (coords) { + // on recoit toujours des coordonnées metriques + var coordinate = {}; + coordinate.x = coords.lon.toFixed(2); + coordinate.y = coords.lat.toFixed(2); + coordinate.unit = "m"; + return coordinate; +}; + +/** + * kilometer + * + * @method _displayKMeter + * @param {Object} coords - coords object {lon, lat} + * @return {Object} coordinate - coordinate object : {x : "214.96", y : "6250.09"} par exemple + * @private + */ +MousePosition.prototype._displayKMeter = function (coords) { + var coordinate = {}; + coordinate.x = (coords.lon / 1000).toFixed(2); + coordinate.y = (coords.lat / 1000).toFixed(2); + coordinate.unit = "km"; + return coordinate; +}; + +// ################################################################### // +// ##################### handlers events to control ################## // +// ################################################################### // + +/** + * this sends the coordinates to the panel. + * (cf. this.GPdisplayCoords() into the DOM functions) + * + * @method _setCoordinate + * @param {Array} coords - coordinate object {lon, lat} + * @private + */ +MousePosition.prototype._setCoordinate = function (coords) { + // structure + // coords + // { + // lon: 5, + // lat : 48 + // } + // + // structure for the coordinates depending on the system type : + // {x:, y:, unit:} or {lng:, lat:} or {lon:, lat:} or {e:, n:, unit:}... + + var coord = []; + var coordinates = {}; + + // transforms the point in the wanted coords system + var oSrs = this._currentProjectionSystems; + var crsProp = oSrs.crs; + + if (!oSrs || !crsProp) { + logger.error("system crs not found"); + return; + } + // reproject coordinates from their CRS of origin (WGS84) to the wanted CRS (crsProp) + if (crsProp !== "EPSG:4326") { + coord = proj4(CRS[crsProp], [coords.lon, coords.lat]); + // projected values are affected to the coord var + coordinates.lon = coord[0]; + coordinates.lat = coord[1]; + } else { + coordinates = coords; + } + + // system type : Geographical or Metric + + var type = this._currentProjectionSystems.type; + + // checks for a formatting function in the wanted unit + var convert = null; + var units = this._projectionUnits[type]; + + for (var i = 0; i < units.length; i++) { + if (units[i].code === this._currentProjectionUnits) { + convert = units[i].convert; + break; + } + } + if (!convert || typeof convert !== "function") { + logger.warn("coordinates format function not found"); + return; + } else { + coord = convert(coordinates); + } + + if (!coord || Object.keys(coord).length === 0) { + return; + } + + this.GPdisplayCoords(coord); +}; + +/** + * this sends the coordinates to the panel. + * (cf. this.GPdisplayElevation() into the DOM functions) + * + * @method _setElevation + * @param {Object} coords - Coordinate position object {lon, lat} + * @private + */ +MousePosition.prototype._setElevation = function (coords) { + // management of the timer of the altitude service request + var delay = this.options.altitude.responseDelay; + this.GPdisplayElevation(coords, delay); +}; + +/** + * this method is triggered when the mouse or the globe is stopped. + * (cf. onMouseMove and onGlobeMove) + * + * @method onMoveStopped + * @param {Object} coords - Coordinate position object {lon, lat} + * @private + */ +MousePosition.prototype.onMoveStopped = function (coords) { + this._setElevation(coords); +}; + +/** + * this method is an handler event to control. The event is 'mousemove' on + * the globe. The handler sends the coordinates to the panel. + * (cf. this.GPdisplayCoords() into the DOM functions) + * + * @method onMouseMove + * @param {Object} e - HTMLElement + * @private + */ +MousePosition.prototype.onMouseMove = function (e) { + var self = this; + + var position = this.getGlobe().getCoordinateFromMouseEvent(e); + if (!position) { + this.GPdisplayCoords({ + lon : "---", + lat : "---" + }); + this.GPresetElevation(); + return; + } + + var coordinate = { + lon : position.x, + lat : position.y + }; + + this._setCoordinate(coordinate); + + // calculation of the altitude after a time limit from the moment where the mouse movement is stopped + if (this.options.displayAltitude) { + clearTimeout(this._timer); + this._timer = setTimeout(function () { + self.onMoveStopped(coordinate); + }, this.options.altitude.triggerDelay); + } +}; + +/** + * this method is an handler event to control. The event is 'moveend' on + * the globe. The handler sends the coordinates to the panel. + * (cf. this.GPdisplayCoords() into the DOM functions) + * + * @method onGlobeMove + * @private + */ +MousePosition.prototype.onGlobeMove = function () { + + // var self = this; + + // info: coordinate = [x, y] + // var coordinate = e.coordinate; + // if ( !e.map || !e.map.getView() ) { + // return; + // } + // var crs = e.map.getView().getProjection(); + // + // this._setCoordinate(coordinate, crs); + // + // // calcul de l'altitude après un certain délai après l'arrêt du mouvement de la carte + // clearTimeout(this._timer); + // this._timer = setTimeout( function () { + // self.onMoveStopped(coordinate, crs); + // }, this.options.altitude.triggerDelay); +}; + +// ################################################################### // +// ####################### handlers events to dom #################### // +// ################################################################### // + +/** + * this method is called by this.GPdisplayElevation() in the dom, and + * it executes a request to the elevation service. + * + * @method onRequestAltitude + * @param {Object} coordinate - {lat:..., lng:...} + * @param {Function} callback - function callback + * @private + */ +MousePosition.prototype.onRequestAltitude = function (coordinate, callback) { + // INFORMATION + // we launch the request to the altitude services + // we implement callbacks in order to retrieve results or errors + // from the service. + // The result is displayed in a DOM element. + // The error messages are display in the dev console (?) + + if (!coordinate || Object.keys(coordinate).length === 0) { + return; + } + + // if we do not want any altitude calculation, we just stop ! + if (!this.options.displayAltitude) { + return; + } + + // if we don not have the rights on the requested resource, we just stop ! + if (this._noRightManagement) { + logger.warn("contract key configuration has no rights to load geoportal elevation "); + document.getElementById(this._addUID("GPmousePositionAlt")).innerHTML = "No rights!"; + return; + } + + // we retrieve the service options... + var options = this.options.altitude.serviceOptions || {}; + + // ... and the coordinates... + options.zonly = true; + options.positions = [{ + lon : coordinate.lon, + lat : coordinate.lat + }]; + + // ... and the callbacks + options.scope = this; + + if (!options.rawResponse) { + // in the general case + options.onSuccess = function (results) { + if (results && Object.keys(results)) { + callback.call(this, results.elevations[0].z); + } + }; + } else { + options.onSuccess = function (results) { + logger.info("alti service raw response : ", results); + }; + } + + options.onFailure = function (error) { + logger.error("[getAltitude] " + error.message); + }; + // in the case of the API key is not given as option of the service, + // we use the key of the autoconf, or the key given in the control options + options.apiKey = options.apiKey || this.options.apiKey; + + // si l'utilisateur a spécifié le paramètre ssl au niveau du control, on s'en sert + // true par défaut (https) + options.ssl = this.options.ssl; + + Gp.Services.getAltitude(options); +}; + +/** + * this method is called by event 'click' on 'GPshowMousePositionPicto' tag label + * (cf. this._createShowMousePositionPictoElement), + * and toggles event 'mousemove' on globe. + * + * @method onShowMousePositionClick + * @private + */ +MousePosition.prototype.onShowMousePositionClick = function () { + // checked : true - panel close + // checked : false - panel open + var globe = this.getGlobe(); + + this.collapsed = this._showMousePositionContainer.checked; + + // event triggered when opening/closing the panel + // and depending on the mode : desktop or tactile! + if (this._showMousePositionContainer.checked) { + // FIXME handle or not mobile case + if (this._isDesktop) { + globe.forget(GlobeViewExtended.EVENTS.MOUSE_MOVE, this._callbacks.mouseMove); + } else { + globe.forget(GlobeViewExtended.EVENTS.CENTER_CHANGED, this.onGlobeMove); + } + } else { + // FIXME handle or not mobile case + if (this._isDesktop) { + globe.listen(GlobeViewExtended.EVENTS.MOUSE_MOVE, this._callbacks.mouseMove); + } else { + globe.listen(GlobeViewExtended.EVENTS.CENTER_CHANGED, this.onGlobeMove); + } + } + + // FIXME + // we handle here the panel display..., but this is not really the good + // place to do it... + this._setElevationPanel(this.options.displayAltitude); + this._setCoordinatesPanel(this.options.displayCoordinates); + if (!this.options.displayCoordinates) { + this._setSettingsPanel(false); + } +}; + +/** + * this method is called by event 'change' on 'GPmousePositionProjectionSystem' + * tag select (cf. this._createMousePositionSettingsElement), + * and selects the system projection. + * + * @method onMousePositionProjectionSystemChange + * @param {Object} e - HTMLElement + * @private + */ +MousePosition.prototype.onMousePositionProjectionSystemChange = function (e) { + var idx = e.target.selectedIndex; // index + var value = e.target.options[idx].value; // crs + + this._setCurrentSystem(value); +}; + +/** + * this method selects the current system projection. + * + * @method _setCurrentSystem + * @param {String} systemCode - inner code (rank in array _projectionSystems) + * @private + */ +MousePosition.prototype._setCurrentSystem = function (systemCode) { + // if we change of system type, we must change the unit type too ! + var type = null; + for (var i = 0; i < this._projectionSystems.length; ++i) { + if (this._projectionSystems[i].code === Number(systemCode)) { + type = this._projectionSystems[i].type; + break; + } + } + + if (!type) { + logger.log("system not found in projection systems container"); + return; + } + + if (type !== this._currentProjectionType) { + this._setTypeUnitsPanel(type); + } + + // registers the current system + this._currentProjectionSystems = this._projectionSystems[Number(systemCode)]; + + // simulates a movement in tactile mode to update the results + if (!this._isDesktop) { + this.onGlobeMove(); + } +}; + +/** + * this method is called by event 'mouseover' on 'GPmousePositionProjectionSystem' + * tag select (cf. this._createMousePositionSettingsElement), + * and selects the system projection whose geoBBox interstects the current view extent. + * + * @method onMousePositionProjectionSystemMouseOver + * @private + */ +MousePosition.prototype.onMousePositionProjectionSystemMouseOver = function () { + // globe infos + var globe = this.getGlobe(); + if (!globe) { + return; + } + + var globeExtent = globe.getExtent(); + + // clear select + var systemList = document.getElementById(this._addUID("GPmousePositionProjectionSystem")); + systemList.innerHTML = ""; + + var option; + + // add systems whose extent intersects the globe extent + for (var j = 0; j < this._projectionSystems.length; j++) { + var proj = this._projectionSystems[j]; + if (proj.geoBBox) { + // bboxes intersection test + if (globeExtent.west > proj.geoBBox.right || + globeExtent.south > proj.geoBBox.top || + globeExtent.east < proj.geoBBox.left || + globeExtent.north < proj.geoBBox.bottom + ) { + if (proj === this._currentProjectionSystems) { + option = document.createElement("option"); + option.value = proj.code; + option.text = proj.label || j; + option.setAttribute("selected", "selected"); + option.setAttribute("disabled", "disabled"); + + systemList.appendChild(option); + } + continue; // do not intersect + } + } + option = document.createElement("option"); + option.value = proj.code; + option.text = proj.label || j; + if (proj === this._currentProjectionSystems) { + option.setAttribute("selected", "selected"); + } + + systemList.appendChild(option); + } +}; + +/** + * this method is called by event 'change' on 'GPmousePositionProjectionUnits' + * tag select (cf. this._createMousePositionSettingsElement), + * and selects the units projection. + * + * @method onMousePositionProjectionUnitsChange + * @param {Object} e - HTMLElement + * @private + */ +MousePosition.prototype.onMousePositionProjectionUnitsChange = function (e) { + var idx = e.target.selectedIndex; + var value = e.target.options[idx].value; + + this._currentProjectionUnits = value; + + // simulates a movement in tactile mode to update the results + if (!this._isDesktop) { + this.onGlobeMove(); + } +}; + +export default MousePosition; diff --git a/src/Itowns-review/Controls/Scale.js b/src/Itowns-review/Controls/Scale.js new file mode 100644 index 000000000..861427bf5 --- /dev/null +++ b/src/Itowns-review/Controls/Scale.js @@ -0,0 +1,152 @@ +import GlobeViewExtended from "../GlobeViewExtended"; +import Utils from "../../Common/Utils"; +import SelectorID from "../../Common/Utils/SelectorID"; +import ScaleDOM from "../../Common/Controls/ScaleDOM"; +import Widget from "./Widget"; + +/** + * @classdesc + * Control to display the scalebar with itowns + * + * @constructor + * @alias itowns.control.Scale + * @extends {itowns.control.Widget} + * @alias itowns.control.Scale + * @param {Object} options - widget options + * @param {String} options.target - HTML target element or HTML target element id + * @param {String} options.position - "absolute" or "relative" + * @example + * var scale = new itowns.control.Scale(); + * + */ +function Scale (options) { + if (!(this instanceof Scale)) { + throw new TypeError("ERROR CLASS_CONSTRUCTOR"); + } + + if (typeof options !== "object") { + throw new Error("ERROR WRONG_TYPE : options should be an object"); + } + + this._initialize(); + + var container = this._initContainer(); + + Widget.call( + this, { + name : "GraphicScale", + element : container, + target : options.target, + position : options.position + } + ); +} + +/* + * @lends module:Scale + */ +Scale.prototype = Object.create(Widget.prototype, {}); + +// retrieves methods of the common class ScaleDOM +Utils.assign(Scale.prototype, ScaleDOM); + +/** + * Constructor (alias) + * + * @private + */ +Scale.prototype.constructor = Scale; + +// ################################################################### // +// ############## public methods (getters, setters) ################## // +// ################################################################### // + +/** + * Bind globe to control + * + * @param {GlobeViewExtended} globe - the globe + */ +Scale.prototype.setGlobe = function (globe) { + // info : this function is called after a globe.addWidget() or a globe.removeWidget() + + if (globe) { // In the case of the adding of a control to the globe + var self = this; + /** + * Definition of the scaleControl callback : + * when the view is changing, we recalculate the graphic scale + */ + this._callbacks.onChangedViewCallback = function () { + var value = globe.pixelsToMeters(200); + value = Math.floor(value); + var digit = Math.pow(10, value.toString().length - 1); + value = Math.round(value / digit) * digit; + var pix = globe.metersToPixels(value); + var unit = "m"; + if (value >= 1000) { + value /= 1000; + unit = "km"; + } + self.getElement().innerHTML = value + " " + unit; + self.getElement().style.width = pix + "px"; + }; + // Ajout des listeners + // initialization + if (globe.isInitialized()) { + this._callbacks.onChangedViewCallback(); + } else { + globe.listen(GlobeViewExtended.EVENTS.GLOBE_INITIALIZED, this._callbacks.onChangedViewCallback); + } + + // At every globe range movement, scale bar may be updated, + globe.listen(GlobeViewExtended.EVENTS.RANGE_CHANGED, this._callbacks.onChangedViewCallback); + } else if (globe == null) { + // we remove the listeners linked to the scalecontrol which has been deleted + this._globe.forget(GlobeViewExtended.EVENTS.GLOBE_INITIALIZED, this._callbacks.onChangedViewCallback); + this._globe.forget(GlobeViewExtended.EVENTS.RANGE_CHANGED, this._callbacks.onChangedViewCallback); + + // if globe == null we remove the scale control + // delete the scaleControl DOM + while (this.getElement().hasChildNodes()) { + this.getElement().removeChild(this.getElement().lastChild); + } + this.getElement().parentNode.removeChild(this.getElement()); + } + + // call original setGlobe method + Widget.prototype.setGlobe.call(this, globe); +}; + +// ################################################################### // +// ##################### init component ############################## // +// ################################################################### // + +/** + * Initialize Scale control (called by constructor) + * + * @private + */ +Scale.prototype._initialize = function () { + // id of the widget : usefull to suffix the CSS ids (to handle cases with several widgets on the same page) + this._uid = SelectorID.generate(); + + // div which will contain the list divs. + this._ScaleContainer = null; + + // callbacks + this._callbacks = {}; +}; + +/** + * Create control main container + * + * @method _initContainer + * @returns {DOMElement} container - widget container + * @private + */ +Scale.prototype._initContainer = function () { + var container = this._createMainContainerElement(); + + return container; +}; + +export default Scale; diff --git a/src/Itowns-review/Controls/Utils/PositionFormater.js b/src/Itowns-review/Controls/Utils/PositionFormater.js new file mode 100644 index 000000000..1073648b0 --- /dev/null +++ b/src/Itowns-review/Controls/Utils/PositionFormater.js @@ -0,0 +1,88 @@ +/** +* implementation : +* cf. http://uihacker.blogspot.fr/2011/07/javascript-formatting-latitudelongitude.html?m=1 +* cf. http://andrew.hedges.name/experiments/convert_lat_long/ +* FIXME formater la sortie +* cf. http://mottie.github.io/javascript-number-formatter/ +* cf. https://github.com/j-/number-formatter +* +*/ +/** ... */ +var PositionFormater = { + + /** ... */ + NORTH : "N", + + /** ... */ + SOUTH : "S", + + /** ... */ + EAST : "E", + + /** ... */ + WEST : "W", + + /** ... */ + digitSecond : 2, + + /** ... */ + digitDecimal : 5, + + /** ... */ + digitRadian : 8, + + roundToDecimal : function (inputNum, numPoints) { + var multiplier = Math.pow(10, numPoints); + return Math.round(inputNum * multiplier) / multiplier; + }, + + decimalToRadian : function (location) { + var d = 0.01745329251994329577; + return this.roundToDecimal(location * d, this.digitRadian); + }, + + decimalToGrade : function (location) { + var d = 1.11111111111111111111; + return this.roundToDecimal(location * d, this.digitRadian); + }, + + decimalToDMS : function (location, hemisphere) { + if (location < 0) { + location *= -1; // strip dash '-' + } + + var degrees = Math.floor(location); // strip decimal remainer for degrees + var minutesFromRemainder = (location - degrees) * 60; // multiply the remainer by 60 + var minutes = Math.floor(minutesFromRemainder); // get minutes from integer + var secondsFromRemainder = (minutesFromRemainder - minutes) * 60; // multiply the remainer by 60 + var seconds = this.roundToDecimal(secondsFromRemainder, this.digitSecond); // get minutes by rounding to integer + + var dms = degrees + "° " + minutes + "' " + seconds + "\" "; + if (hemisphere) { + dms += hemisphere; + } + + return dms; + }, + + decimalLatToDMS : function (location) { + var hemisphere = (location < 0) ? this.SOUTH : this.NORTH; // south if negative + return this.decimalToDMS(location, hemisphere); + }, + + decimalLongToDMS : function (location) { + var hemisphere = (location < 0) ? this.WEST : this.EAST; // west if negative + return this.decimalToDMS(location, hemisphere); + }, + + DMSToDecimal : function (degrees, minutes, seconds, hemisphere) { + var ddVal = degrees + minutes / 60 + seconds / 3600; + ddVal = (hemisphere === this.SOUTH || hemisphere === this.WEST) ? ddVal * -1 : ddVal; + + var decimal = this.roundToDecimal(ddVal, this.digitDecimal); + return decimal; + } + +}; + +export default PositionFormater; diff --git a/src/Itowns-review/Controls/Widget.js b/src/Itowns-review/Controls/Widget.js new file mode 100644 index 000000000..63d793884 --- /dev/null +++ b/src/Itowns-review/Controls/Widget.js @@ -0,0 +1,112 @@ +import Logger from "../../Common/Utils/LoggerByDefault"; + +var logger = Logger.getLogger("Widget"); + +/** +* @classdesc +* iTowns Widget class. +* Every geoportal control inherits of this class. +* +* @constructor +* @alias itowns.control.Widget +* @param {Object} options - options for function call. +* @param {String} options.name - Name of the widget. +* @param {Object} options.element - HTML element of the widget +* @param {Object|String} options.target - HTML element or HTML element id where to put the widget +* @param {String} options.position - "absolute" or "relative" +* @example +* var myWidget = new itowns.control.Widget({ +* name : "myWidget", +* element : myWidgetDiv, +* target : myWidgetTargetDiv, +* position: "absolute" +* }); +*/ +function Widget (options) { + this._name = (options.name !== undefined) ? options.name : null; + this._element = (options.element !== undefined) ? options.element : null; + this._position = (options.position !== undefined) ? options.position : null; + this._target = null; + this._globe = null; + + if (options.target) { + this.setTarget(options.target, this._position); + } +} + +/** + * Constructor (alias) + */ +Widget.prototype.constructor = Widget; + +/** + * Return the widget's container element. + * + * @method + * @return {HTMLElement} widget's container element. + */ +Widget.prototype.getElement = function getElement () { + return this._element; +}; + +/** + * Associates the widget to a specified target div. + * + * @method + * @param {HTMLElement|String} target - widget target div html element or target div id. + * @param {String} position - html position attribute. + */ +Widget.prototype.setTarget = function setTarget (target, position) { + this._target = typeof target === "string" ? document.getElementById(target) : target; + + if (!this._element) { + logger.error("Widget:setTarget - widget element not created"); + return; + } + + this._element.style.position = position || "relative"; + + this._target.appendChild(this._element); +}; + +/** + * Return the widget's target div. + * + * @method + * @return {HTMLElement} widget's target div. + */ +Widget.prototype.getTarget = function getTarget () { + return this._target; +}; + +/** + * Return the widget's element position. + * + * @method + * @return {String} widget's element position. + */ +Widget.prototype.getPosition = function getPosition () { + return this._position; +}; + +/** + * Get the globe associated with the widget. Undefined if the widget is not added to a globe. + * + * @method + * @return {Object} globe + */ +Widget.prototype.getGlobe = function getGlobe () { + return this._globe; +}; + +/** + * Associate a globe to the widget. + * + * @method + * @param {Object} globe - Globe to associate to the widget. + */ +Widget.prototype.setGlobe = function setGlobe (globe) { + this._globe = globe; +}; + +export default Widget; diff --git a/src/Itowns-review/GlobeViewExtended.js b/src/Itowns-review/GlobeViewExtended.js new file mode 100644 index 000000000..a5bbb7d87 --- /dev/null +++ b/src/Itowns-review/GlobeViewExtended.js @@ -0,0 +1,848 @@ +import Logger from "../Common/Utils/LoggerByDefault"; +import { + GlobeView as ItGlobeView, + Coordinates as ItCoordinates, + ColorLayersOrdering as ItColorLayersOrdering, + FeaturesUtils as ItFeaturesUtils, + Fetcher as ItParser, + MAIN_LOOP_EVENTS as IT_MAIN_LOOP_EVENTS, + CONTROL_EVENTS as IT_CONTROL_EVENTS, + GLOBE_VIEW_EVENTS as IT_GLOBE_VIEW_EVENTS, + VIEW_EVENTS as IT_VIEW_EVENTS +} from "itowns"; + +/* import GlobeView, { GLOBE_VIEW_EVENTS } from "itowns/Core/Prefab/GlobeView"; +import Coordinates from "itowns/Core/Geographic/Coordinates"; +import ColorLayersOrdering from "itowns/Renderer/ColorLayersOrdering"; +import FeaturesUtils from "itowns/Utils/FeaturesUtils"; +import { MAIN_LOOP_EVENTS } from "itowns/Core/MainLoop"; +import { CONTROL_EVENTS } from "itowns/Controls/GlobeControls"; +import { VIEW_EVENTS } from "itowns/Core/View"; */ + +var logger = Logger.getLogger("GlobeViewExtended"); + +/** + * @classdesc + * + * Extended itowns.GlobeView. + * + * @constructor + * @extends {itowns.GlobeView} + * @param {HTMLElement} viewerDiv - Where to instanciate the Three.js scene in the DOM + * @param {Object} coordCarto - longitude, latitude, altitude + * @param {Object} [options] - Optional properties. + * @param {String} [options.position="relative"] - "absolute" or "relative" + */ +function GlobeViewExtended (viewerDiv, coordCarto, options) { + if (!viewerDiv.style.position || (options & options.position)) { + viewerDiv.style.position = (!options || !options.position) ? "relative" : options.position; + } + + // stockage de l'élément html porteur du globe + var globeViewDiv = document.createElement("div"); + globeViewDiv.style.width = "100%"; + globeViewDiv.style.height = "100%"; + viewerDiv.appendChild(globeViewDiv); + this._viewerDiv = viewerDiv; + + // widget container + this._widgets = []; + + // mapping des evenements + this._initEventMap(); + + // pour savoir si le globe est initialise + this._isInitialized = false; + + // call constructor + this._globeView = new ItGlobeView(globeViewDiv, coordCarto, options); + + var self = this; + this.listen(GlobeViewExtended.EVENTS.GLOBE_INITIALIZED, function () { + self._isInitialized = true; + }); + + this._globeView.addFrameRequester(IT_MAIN_LOOP_EVENTS.BEFORE_RENDER, function () { + clearTimeout(this._preRenderTimer); + self._preRenderTimer = setTimeout(function () { + var visibleColorLayersIds = []; + var visibleElevationLayersIds = []; + + for (var i = 0; i < self.getGlobeView().tileLayer.info.displayed.layers.length; ++i) { + if (self.getGlobeView().tileLayer.info.displayed.layers[i].isColorLayer) { + visibleColorLayersIds.push(self.getGlobeView().tileLayer.info.displayed.layers[i].id); + } + if (self.getGlobeView().tileLayer.info.displayed.layers[i].isElevationLayer) { + visibleElevationLayersIds.push(self.getGlobeView().tileLayer.info.displayed.layers[i].id); + } + } + var currentExtent = self.getGlobeView().tileLayer.info.displayed.extent; + self._globeView.dispatchEvent({ + type : GlobeViewExtended.EVENTS.PRE_RENDER, + colorLayersId : visibleColorLayersIds, + elevationLayersId : visibleElevationLayersIds, + extent : currentExtent + }); + }, 100); + }.bind(this)); + + if (this._globeView.controls) { + this.freezeControl(); + } +} + +/** + * intializes the evenements map + */ +GlobeViewExtended.prototype._initEventMap = function () { + if (!GlobeViewExtended.EVENTS) { + GlobeViewExtended.EVENTS = { + RANGE_CHANGED : IT_CONTROL_EVENTS.RANGE_CHANGED, + CENTER_CHANGED : IT_CONTROL_EVENTS.CAMERA_TARGET_CHANGED, + ORIENTATION_CHANGED : IT_CONTROL_EVENTS.ORIENTATION_CHANGED, + LAYER_ADDED : IT_GLOBE_VIEW_EVENTS.LAYER_ADDED, + LAYER_REMOVED : IT_GLOBE_VIEW_EVENTS.LAYER_REMOVED, + LAYERS_ORDER_CHANGED : IT_GLOBE_VIEW_EVENTS.COLOR_LAYERS_ORDER_CHANGED, + GLOBE_INITIALIZED : IT_GLOBE_VIEW_EVENTS.GLOBE_INITIALIZED, + LAYERS_INITIALIZED : IT_VIEW_EVENTS.LAYERS_INITIALIZED, + VIEW_INITIALIZED : "viewinitialized", + PRE_RENDER : "prerender", + MOUSE_MOVE : "mousemove", + AFTER_RENDER : IT_MAIN_LOOP_EVENTS.AFTER_RENDER, + OPACITY_PROPERTY_CHANGED : "opacity-property-changed", + VISIBLE_PROPERTY_CHANGED : "visible-property-changed", + SEQUENCE_PROPERTY_CHANGED : "sequence-property-changed" + }; + } +}; + +/** + * Constructor (alias) + */ +GlobeViewExtended.prototype.constructor = GlobeViewExtended; + +/** + * Get GlobeViex Object (parent) + * @returns {Object} itowns GlobeView object + */ +GlobeViewExtended.prototype.getGlobeView = function () { + return this._globeView; +}; + +/** + * Indicates if the globe is initialized or not + * + * @return {Boolean} isInitialized + * + */ +GlobeViewExtended.prototype.isInitialized = function () { + return this._isInitialized; +}; + +/** + * Detects when the camera movement stops, then launch the callback given as parameter + * + * @param {Function} cb - The function to execute when the event occures. + * + */ +GlobeViewExtended.prototype.onCameraMoveStop = function (cb) { + var self = this; + function afterRenderHandler () { + self._globeView.removeFrameRequester(IT_MAIN_LOOP_EVENTS.AFTER_CAMERA_UPDATE, afterRenderHandler); + cb(); + }; + this._globeView.addFrameRequester(IT_MAIN_LOOP_EVENTS.AFTER_CAMERA_UPDATE, afterRenderHandler); +}; + +/** + * Disables globe controls until the globe rendering is completed + */ +GlobeViewExtended.prototype.freezeControl = function () { + // disable navigation + this._globeView.controls.enabled = false; + + this.onCameraMoveStop(function () { + this._globeView.controls.enabled = true; + }.bind(this)); +}; + +/** + * Associates a function to trigger when an event is received. + * + * @param {String} type - the event type. Can be any of {@link EVENTS} + * @param {Function} callback - The function to execute when the event occures. + * @return {Object} key - The event key + * + */ +GlobeViewExtended.prototype.listen = function (type, callback) { + if (typeof (callback) !== "function") { + logger.warn("no callback provided for event : " + type); + return null; + } + + var target = this._getEventTarget(type); + if (!target) { + return null; + } + + if (type === GlobeViewExtended.EVENTS.AFTER_RENDER) { + target.addFrameRequester(type, callback); + } else { + target.addEventListener(type, callback); + } + + return { + target : target, + callback : callback, + type : type + }; +}; + +/** + * Associates a function to trigger when a layer event is received. + * + * @param {Object} layer - The itowns layer. + * @param {String} type - the event type. Can be any of {@link EVENTS}. + * @param {Function} callback - The function to execute when the event occures. + * @return {Object} key - The event key + * + */ +GlobeViewExtended.prototype.addLayerListener = function (layer, type, callback) { + if (typeof (callback) !== "function") { + logger.warn("no callback provided for event : " + type); + return null; + } + layer.addEventListener(type, callback); + return { + target : layer, + callback : callback, + type : type + }; +}; + +/** + * Returns the target of a given event type + * + * @param {String} type - the event type. Can be any of {@link EVENTS} + * @return {Object} target - The event target. + * + */ +GlobeViewExtended.prototype._getEventTarget = function (type) { + switch (type) { + case GlobeViewExtended.EVENTS.RANGE_CHANGED: + case GlobeViewExtended.EVENTS.CENTER_CHANGED: + case GlobeViewExtended.EVENTS.ORIENTATION_CHANGED: + return this.getGlobeView().controls; + case GlobeViewExtended.EVENTS.LAYER_ADDED: + case GlobeViewExtended.EVENTS.LAYER_REMOVED: + case GlobeViewExtended.EVENTS.LAYERS_ORDER_CHANGED: + case GlobeViewExtended.EVENTS.LAYERS_INITIALIZED: + case GlobeViewExtended.EVENTS.GLOBE_INITIALIZED: + case GlobeViewExtended.EVENTS.PRE_RENDER: + case GlobeViewExtended.EVENTS.AFTER_RENDER: + case GlobeViewExtended.EVENTS.VIEW_INITIALIZED: + return this.getGlobeView(); + case GlobeViewExtended.EVENTS.MOUSE_MOVE: + return this._viewerDiv; + default: + logger.warn("unhandled event : " + type); + return null; + } +}; + +/** + * Cancels an event listening + * + * @param {Object} key - The event key + * + */ +GlobeViewExtended.prototype.forgetByKey = function (key) { + if (key.type === GlobeViewExtended.EVENTS.AFTER_RENDER) { + key.target.removeFrameRequester(key.type, key.callback); + } else { + key.target.removeEventListener(key.type, key.callback); + } +}; + +/** + * Cancels an layer event listening + * + * @param {Object} layer - The itowns layer + * @param {String} type - the event type + * @param {Function} callback - The function to execute when the event occures + * + */ +GlobeViewExtended.prototype.removeLayerListener = function (layer, type, callback) { + this.forgetByKey({ + target : layer, + callback : callback, + type : type + }); +}; + +/** + * Cancels an event listening + * + * @param {Object} type - The event type + * @param {Function} callback - The event handler + */ +GlobeViewExtended.prototype.forget = function (type, callback) { + var target = this._getEventTarget(type); + if (!target) return; + + this.forgetByKey({ + target : target, + callback : callback, + type : type + }); +}; + +/** + * Overload itowns.GlobeView addLayer method + * + * @param {Object} layer - The itowns layer + * @return {Promise} promise + */ +GlobeViewExtended.prototype.addLayer = function (layer) { + // FIXME : to delete when itowns commit 2e9ed61eb4aa2a4bbe0e17c8e2650953844b099e + // is integrated into an iTowns release + try { + var promise = this.getGlobeView().addLayer(layer); + } catch (error) { + return Promise.reject(error); + } + + return promise; +}; + +/** + * Overload itowns.GlobeView removeLayer method + * + * @param {String} layerId - The layer id + */ +GlobeViewExtended.prototype.removeLayer = function (layerId) { + this.getGlobeView().removeLayer(layerId); +}; + +/** + * Set layer opacity + * + * @param {String} layerId - Layer id + * @param {Number} opacityValue - opacity value in [0 1] + */ +GlobeViewExtended.prototype.setLayerOpacity = function (layerId, opacityValue) { + var layer = this.getColorLayerById(layerId); + layer.opacity = opacityValue; + this.getGlobeView().notifyChange(layer); +}; + +/** + * Set layer visibility + * + * @param {String} layerId - Layer id + * @param {Boolean} visible - New visibility of the layer + */ +GlobeViewExtended.prototype.setLayerVisibility = function (layerId, visible) { + var layer = this.getColorLayerById(layerId); + layer.visible = visible; + this.getGlobeView().notifyChange(layer); +}; + +/** + * Move layer to the specified index + * + * @param {String} layerId - Layer id + * @param {Boolean} index - new index of the layer + */ +GlobeViewExtended.prototype.moveLayerToIndex = function (layerId, index) { + ItColorLayersOrdering.moveLayerToIndex(this.getGlobeView(), layerId, index); +}; + +/** + * Remove event listener from the globe + * + * @param {String} type - event type + * @param {Function} callback - event handler + */ +GlobeViewExtended.prototype.removeEventListener = function (type, callback) { + switch (type) { + case "mousemove": + this._viewerDiv.removeEventListener(type, callback); + break; + case "centerchanged": + this.getGlobeView().controls.removeEventListener(type, callback); + break; + default: + this.getGlobeView().removeEventListener(type, callback); + break; + } +}; + +/** + * Defines if the current view extent have to be computed on pre-render event + * + * @param {Boolean} b - tells if the view extent info should be fetched by the event PRE_RENDER + */ +GlobeViewExtended.prototype.preRenderEventFetchViewExtent = function (b) { + if (typeof b === "undefined") { + b = true; + } + this._fetchExtent = b; +}; + +/** + * Defines if the list of the color layers displayed have to be computed on pre-render event + * + * @param {Boolean} b - tells if the displayed color layers info should be fetched by the event PRE_RENDER + */ +GlobeViewExtended.prototype.preRenderEventFetchColorLayersDisplayed = function (b) { + if (typeof b === "undefined") { + b = true; + } + this._fetchVisibleColorLayers = b; +}; + +/** + * Defines if the list of the elevation layers displayed have to be computed on pre-render event + * + * @param {Boolean} b - tells if the displayed elevation layers info should be fetched by the event PRE_RENDER + */ +GlobeViewExtended.prototype.preRenderEventFetchElevationLayersDisplayed = function (b) { + if (typeof b === "undefined") { + b = true; + } + this._fetchVisibleElevationLayers = b; +}; + +/** + * Defines if the list of the layers of all types displayed have to be computed on pre-render event + * + * @param {Boolean} b - tells if both displayed color layers and displayed elevation layers infos should be fetched by the event PRE_RENDER + */ +GlobeViewExtended.prototype.preRenderEventFetchLayersDisplayed = function (b) { + if (typeof b === "undefined") { + b = true; + } + this._fetchVisibleColorLayers = b; + this._fetchVisibleElevationLayers = b; +}; + +/** + * Get layer by its id + * + * @param {String} layerId - Layer id + * @return {Object} layer Object + */ +GlobeViewExtended.prototype.getLayerById = function (layerId) { + var layer = this.getGlobeView().getLayers(function (l) { + if (l.id === layerId) { + return l; + } + })[0]; + if (!layer) { + logger.trace("[GlobeViewExtended] : no Layer found for the id '" + layerId + "'"); + return; + } + return layer; +}; + +/** + * Get color layer by its id + * + * @param {String} layerId - Color layer id + * @return {Object} layer Object + */ +GlobeViewExtended.prototype.getColorLayerById = function (layerId) { + var layer = this.getGlobeView().getLayers(function (l) { + if (l.id === layerId && l.isColorLayer) { + return l; + } + })[0]; + if (!layer) { + logger.trace("[GlobeViewExtended] : no colorLayer found for the id '" + layerId + "'"); + return; + } + return layer; +}; + +/** + * Get imagery layers + * + * @return {Array} imagery layers + */ +GlobeViewExtended.prototype.getColorLayers = function () { + return this.getGlobeView().getLayers(function (layer) { + if (layer.isColorLayer) { + return layer; + } + }); +}; + +/** + * Get vector layers + * + * @return {Array} vector layers + */ +GlobeViewExtended.prototype.getVectorLayers = function () { + return this.getGlobeView().getLayers(function (layer) { + if (layer.source && layer.source.isFileSource) { + return layer; + } + }); +}; + +/** + * Get elevation layers + * + * @return {Array} elevation layers + */ +GlobeViewExtended.prototype.getElevationLayers = function () { + return this.getGlobeView().getLayers(function (layer) { + if (layer.isElevationLayer) { + return layer; + } + }); +}; + +/** + * Get the current view extent + * + * @returns {Array} current view extent + */ +GlobeViewExtended.prototype.getExtent = function () { + return this.getGlobeView().tileLayer.info.displayed.extent; +}; + +/** + * Add a widget to the globe + * + * @param {Object} widget - The Widget object to add + */ +GlobeViewExtended.prototype.addWidget = function (widget) { + if (!widget.getTarget()) { + // default position value is 'absolute' if the target div is the viewer div + widget.setTarget(this._viewerDiv, widget.getPosition() ? widget.getPosition() : "absolute"); + } + widget.setGlobe(this); + this._widgets.push(widget); +}; + +/** + * Returns all widgets. + * + * @return {Array} widgets - The array of widgets. + */ +GlobeViewExtended.prototype.getWidgets = function () { + return this._widgets; +}; + +/** + * Removes a widget. + * + * @param {Object} widget - The Widget object to remove + */ +GlobeViewExtended.prototype.removeWidget = function (widget) { + widget.setGlobe(); + for (var idx = 0; idx < this._widgets.length; idx++) { + if (this._widgets[idx] === widget) { + this._widgets.splice(idx, 1); + } + } +}; + +/** + * Get html target element + * + * @return {HTMLElement} Globe container element + */ +GlobeViewExtended.prototype.getTargetElement = function () { + return this._viewerDiv; +}; + +/** + * Returns current view scale + * + * @return {Number} Scale + */ +GlobeViewExtended.prototype.getScale = function () { + return this.getGlobeView().getScale(); +}; + +/** + * Sets tilt + * + * @param {Number} tilt - Tilt value + * @return {Promise} + */ +GlobeViewExtended.prototype.setTilt = function (tilt) { + return this.getGlobeView().controls.setTilt(tilt, false); +}; + +/** + * Returns tilt + * + * @return {Number} - Tilt + */ +GlobeViewExtended.prototype.getTilt = function () { + return this.getGlobeView().controls.getTilt(); +}; + +/** + * Sets azimuth + * + * @param {Number} azimuth - Azimuth value + * @return {Promise} + */ +GlobeViewExtended.prototype.setAzimuth = function (azimuth) { + return this.getGlobeView().controls.setHeading(azimuth, false); +}; + +/** + * Returns azimuth + * + * @return {Number} azimuth + */ +GlobeViewExtended.prototype.getAzimuth = function () { + return this.getGlobeView().controls.getHeading(); +}; + +/** + * Gets the coordinate in lat,lon for a given pixel. + * + * @param {Number} x - The pixel x-position inside the Globe element. + * @param {Number} y - The pixel y-position inside the Globe element. + * @return {Coordinates} position + */ +GlobeViewExtended.prototype.getCoordinateFromPixel = function (x, y) { + return this.getGlobeView().controls.pickGeoPosition({ + x : x, + y : y + }); +}; + +/** + * Gets the coordinate in lat,lon for a given mouse position. + * + * @param {MouseEvent} mouseEvent - A mouse event. + * @return {Coordinates} position + */ +GlobeViewExtended.prototype.getCoordinateFromMouseEvent = function (mouseEvent) { + var coords = this.getGlobeView().eventToViewCoords(mouseEvent); + return this.getGlobeView().controls.pickGeoPosition(coords); +}; + +/** + * Get all visible features that intersect a pixel + * + * @param {MouseEvent} mouseEvent - A mouse event. + * @return {Array} visibleFeatures - The array of visible features. + */ +GlobeViewExtended.prototype.getFeaturesAtMousePosition = function (mouseEvent) { + var vectorLayers = this.getVectorLayers(); + if (!vectorLayers) { + return; + } + // array of the visible features on the clicker coord + var visibleFeatures = []; + var geoCoord = this.getCoordinateFromMouseEvent(mouseEvent); + if (geoCoord) { + // buffer around the click inside we retrieve the features + var precision = this.getGlobeView().controls.pixelsToDegrees(5); + for (var i = 0; i < vectorLayers.length; i++) { + var idx; + var layer = vectorLayers[i]; + // if the layer is not visible, we ignore it + if (!layer.visible) { + continue; + } + var result = ItFeaturesUtils.filterFeaturesUnderCoordinate(geoCoord, layer.source.parsedData, precision); + // we add the features to the visible features array + for (idx = 0; idx < result.length; idx++) { + visibleFeatures.push(result[idx]); + } + } + } + return visibleFeatures; +}; + +/** + * Changes the center of the scene on screen to the specified in lat, lon. + * + * @param {Object} center - Center object + * @param {Number} center.longitude - Coordinate longitude WGS84 in degree + * @param {Number} center.latitude - Coordinate latitude WGS84 in degree + * @return {Promise} A promise that resolves when the next 'globe initilazed' event fires. + */ +GlobeViewExtended.prototype.setCameraTargetGeoPosition = function (center) { + const itownsCoord = this._transformCoords(center); + return this.getGlobeView().controls.lookAtCoordinate(itownsCoord, false); +}; + +/** + * Retuns the coordinates of the central point on screen in lat,lon and alt + * + * @return {Object} center + */ +GlobeViewExtended.prototype.getCenter = function () { + var cameraCenter = this.getGlobeView().controls.getLookAtCoordinate(); + return this._fromItownsCoords(cameraCenter); +}; + +/** + * Returns the actual zoom. + * + * @return {Number} zoom + */ +GlobeViewExtended.prototype.getZoom = function () { + return this.getGlobeView().controls.getZoom(); +}; + +/** + * Sets the current zoom. + * + * @param {Number} zoom - The zoom + * @return {Promise} promise + */ +GlobeViewExtended.prototype.setZoom = function (zoom) { + return this.getGlobeView().controls.setZoom(zoom, false); +}; + +/** + * To convert the projection in meters on the globe of a number of pixels of screen + * @param {Number} pixels - count pixels to project + * @return {Number} projection in meters on globe + */ +GlobeViewExtended.prototype.pixelsToMeters = function (pixels) { + return this.getGlobeView().getPixelsToMeters(pixels); +}; + +/** + * Projection on screen in pixels of length in meter on globe + * @param {Number} value - Length in meter on globe + * @return {Number} projection in pixels on screen + */ +GlobeViewExtended.prototype.metersToPixels = function (value) { + return this.getGlobeView().getMetersToPixels(value); +}; + +/** + * Returns the "range": the distance in meters between the camera and the current central point on the screen. + * @return {Number} number + */ +GlobeViewExtended.prototype.getRange = function () { + return this.getGlobeView().controls.getRange(); +}; + +/** + * @return {THREE.Vector3} position + */ +GlobeViewExtended.prototype.getCameraTargetPosition = function () { + return this.getGlobeView().controls.getCameraTargetPosition(); +}; + +/** + * To get the layer event infos + * + * @param {Object} evt - event + * @returns {Object} object with event properties + */ +GlobeViewExtended.prototype.getLayerEventInfos = function (evt) { + var propertyName = evt.type.replace("-property-changed", ""); + return { + propertyName : propertyName, + previousValue : evt.previous[propertyName], + newValue : evt.new[propertyName] + }; +}; + +/** + * Sets background (specific to miniglobe) + */ +GlobeViewExtended.prototype.setBackground = function () { + // Set a 0 alpha clear value (instead of the default '1') + // because we want a transparent background for the miniglobe view to be able + // to see the main view "behind" + this.getGlobeView().mainLoop.gfxEngine.renderer.setClearColor(0x000000, 0); +}; + +/** + * Sets camera position + * @param {THREE.Vector3} target - Target position + * @param {Number} distance - Distance from target + */ +GlobeViewExtended.prototype.setCameraPosition = function (target, distance) { + this.getGlobeView().camera.camera3D.position.copy(target).setLength(distance); +}; + +/** + * Sets camera orientation to look at specified target + * @param {THREE.Vector3} target - Target position + */ +GlobeViewExtended.prototype.lookAt = function (target) { + this.getGlobeView().camera.camera3D.lookAt(target); +}; + +/** + * Notifies the scene it needs to be updated + * @param {String} styleUrl - style url + * @returns {Object} json object + */ +GlobeViewExtended.prototype.parseMapboxStyle = function (styleUrl) { + return ItParser.json(styleUrl); +}; + +/** + * Notifies the scene it needs to be updated + */ +GlobeViewExtended.prototype.notifyChange = function () { + this.getGlobeView().notifyChange(this.getGlobeView().camera.camera3D); +}; + +/** +* Resizes itowns +* +* @param {Integer} width - canvas width in pixels +* @param {Integer} height - canvas height in pixels +*/ +GlobeViewExtended.prototype.resize = function (width, height) { + this.getGlobeView().mainLoop.gfxEngine.onWindowResize(width, height); + this.notifyChange(); +}; + +/** +* Transform to itowns coordinates +* +* @param {Object} coordCarto - longitude, latitude, altitude +* @returns {Object} itowns coordinates +*/ +GlobeViewExtended.prototype._transformCoords = function (coordCarto) { + if (coordCarto === undefined) return; + + const itownsCoord = {}; + + if (coordCarto.zoom !== undefined) itownsCoord.zoom = coordCarto.zoom; + if (coordCarto.tilt !== undefined) itownsCoord.tilt = coordCarto.tilt; + if (coordCarto.heading !== undefined) itownsCoord.heading = coordCarto.heading; + + if (coordCarto.longitude !== undefined && coordCarto.latitude !== undefined) { + const altitude = coordCarto.altitude || 0; + itownsCoord.coord = new ItCoordinates("EPSG:4326", coordCarto.longitude, coordCarto.latitude, altitude); + } + return itownsCoord; +}; + +/** +* Transform from itowns coordinates +* +* @param {Object} itownsCoord - itowns coordinates +* @returns {Object} coordinates +*/ +GlobeViewExtended.prototype._fromItownsCoords = function (itownsCoord) { + return { + lon : itownsCoord.x, + lat : itownsCoord.y, + alt : itownsCoord.z + }; +}; + +export default GlobeViewExtended; diff --git a/src/Itowns-review/Layer/LayerElevation.js b/src/Itowns-review/Layer/LayerElevation.js new file mode 100644 index 000000000..887078424 --- /dev/null +++ b/src/Itowns-review/Layer/LayerElevation.js @@ -0,0 +1,131 @@ +/* globals self */ +import Gp from "geoportal-access-lib"; +import Utils from "../../Common/Utils"; +import Config from "../../Common/Utils/Config"; +import Logger from "../../Common/Utils/LoggerByDefault"; +import Pkg from "../../../package.json"; +import { + Extent as ItExtent, + WMTSSource as ItWMTSSource, + ElevationLayer as ItElevationLayer +} from "itowns"; +/* import Extent from "itowns/Core/Geographic/Extent"; +import WMTSSource from "itowns/Source/WMTSSource"; +import ElevationLayer from "itowns/Layer/ElevationLayer"; */ + +var logger = Logger.getLogger("elevationLayer"); + +/** + * @classdesc + * Geoportal elevation source creation + * + * @constructor + * @alias itowns.layer.GeoportalElevation + * @param {Object} options - options for function call. + * @param {String} options.layer - Elevation layer name (e.g. "ELEVATION.ELEVATIONGRIDCOVERAGE") + * @param {Boolean} [options.ssl] - if set true, enforce protocol https (only for nodejs) + * @param {String} [options.apiKey] - Access key to Geoportal platform + * @param {Object} [options.itownsParams] - options to overload default geoportal layer options for itowns.GlobeView.addLayer function (see {@link http://www.itowns-project.org/itowns/API_Doc/GlobeView.html#addLayer GlobeView.addLayer}) + * @example + * var geoportalElevation = new itowns.layer.GeoportalElevation({ + * layer : "ELEVATION.ELEVATIONGRIDCOVERAGE" + * }); + */ +function LayerElevation (options) { + if (!(this instanceof LayerElevation)) { + throw new TypeError("ERROR CLASS_CONSTRUCTOR"); + } + + // check layer params + if (!options.layer) { + throw new Error("ERROR PARAM_MISSING : layer"); + } + if (typeof options.layer !== "string") { + throw new Error("ERROR WRONG TYPE : layer"); + } + + // par defaut + if (typeof options.ssl === "undefined") { + options.ssl = false; + } + + // Check if configuration is loaded + if (!Config.isConfigLoaded()) { + throw new Error("ERROR : contract key configuration has to be loaded to load Geoportal layers. See http://ignf.github.io/evolution-apigeoportail/ol3/ol3-autoconf.html"); + } + + var layerId = Config.getLayerId(options.layer, "WMTS"); + + if (layerId && Config.configuration.getLayerConf(layerId)) { + var config = {}; + var wmtsParams = Config.getLayerParams(options.layer, "WMTS", options.apiKey); + + if (wmtsParams.projection === "EPSG:3857" && wmtsParams.extent) { + wmtsParams.extent = new ItExtent("EPSG:4326", wmtsParams.extent.left, wmtsParams.extent.right, wmtsParams.extent.bottom, wmtsParams.extent.top).as("EPSG:3857"); + } else { + wmtsParams.projection = "EPSG:4326"; + wmtsParams.extent = new ItExtent("EPSG:4326", wmtsParams.extent.left, wmtsParams.extent.right, wmtsParams.extent.bottom, wmtsParams.extent.top); + } + + // gestion de mixContent dans l'url du service... + var ctx = typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : null; + var protocol = (ctx) + ? (ctx.location && ctx.location.protocol && ctx.location.protocol.indexOf("https:") === 0 ? "https://" : "http://") + : (options.ssl ? "https://" : "http://"); + + config.id = layerId; + config.noDataValue = -99999; + config.updateStrategy = { + type : 0, + options : { + groups : [11, 14] + } + }; + config.source = new ItWMTSSource({ + protocol : "wmts", + url : wmtsParams.url.replace(/(http|https):\/\//, protocol), + networkOptions : { + crossOrigin : "omit" + }, + attribution : wmtsParams.originators, + projection : wmtsParams.projection, + name : options.layer, + format : "image/x-bil;bits=32", + tileMatrixSet : wmtsParams.TMSLink, + tileMatrixSetLimits : wmtsParams.tileMatrixSetLimits, + extent : { + west : wmtsParams.extent.west, + east : wmtsParams.extent.east, + south : wmtsParams.extent.south, + north : wmtsParams.extent.north + } + }); + + // ajout du tag gp-itowns-ext dans les requêtes WMTS elevation + config.source.url = Gp.Helper.normalyzeUrl(config.source.url, { + "gp-itowns-ext" : Pkg.itownsExtVersion || Pkg.version + }, false); + + // récupération des autres paramètres passés par l'utilisateur + Utils.mergeParams(config, options.itownsParams); + + // add legends and metadata (to be added to LayerSwitcher control) + config.legends = wmtsParams.legends; + config.metadata = wmtsParams.metadata; + config.description = wmtsParams.description; + config.title = wmtsParams.title; + config.quicklookUrl = wmtsParams.quicklookUrl; + + return new ItElevationLayer(config.id, config); + } else { + // If layer is not in Gp.Config + logger.log("[source WMTS] ERROR : " + options.layer + " cannot be found in Geoportal Configuration. Make sure that this resource is included in your contract key."); + } +} + +/* + * Constructor (alias) + */ +LayerElevation.prototype.constructor = LayerElevation; + +export default LayerElevation; diff --git a/src/Itowns-review/Layer/LayerWMS.js b/src/Itowns-review/Layer/LayerWMS.js new file mode 100644 index 000000000..245b0815d --- /dev/null +++ b/src/Itowns-review/Layer/LayerWMS.js @@ -0,0 +1,126 @@ +import Gp from "geoportal-access-lib"; +import Utils from "../../Common/Utils"; +import Config from "../../Common/Utils/Config"; +import Logger from "../../Common/Utils/LoggerByDefault"; +import Pkg from "../../../package.json"; +import { + Extent as ItExtent, + WMSSource as ItWMSSource, + ColorLayer as ItColorLayer +} from "itowns"; +/* import Extent from "itowns/Core/Geographic/Extent"; +import WMSSource from "itowns/Source/WMSSource"; +import ColorLayer from "itowns/Layer/ColorLayer"; */ + +var logger = Logger.getLogger("wmsLayer"); + +/** + * @classdesc + * Geoportal WMTS source creation + * + * @constructor + * @alias itowns.layer.GeoportalWMS + * @param {Object} options - options for function call. + * @param {String} options.layer - Layer name (e.g. "ORTHOIMAGERY.ORTHOPHOTOS") + * @param {Boolean} [options.ssl = true] - use of ssl or not (default true, service requested using https protocol) + * @param {String} [options.apiKey] - Access key to Geoportal platform + * @param {Object} [options.itownsParams] - other options for itowns.GlobeView.addLayer function (see {@link http://www.itowns-project.org/itowns/API_Doc/GlobeView.html#addLayer GlobeView.addLayer}) + * @example + * var geoportalWMS = new itowns.layer.GeoportalWMS({ + * layer : "ORTHOIMAGERY.ORTHOPHOTOS" + * }); + */ +function LayerWMS (options) { + if (!(this instanceof LayerWMS)) { + throw new TypeError("ERROR CLASS_CONSTRUCTOR"); + } + + // check layer params + if (!options.layer) { + throw new Error("ERROR PARAM_MISSING : layer"); + } + if (typeof options.layer !== "string") { + throw new Error("ERROR WRONG TYPE : layer"); + } + + // par defaut + if (typeof options.ssl === "undefined") { + options.ssl = true; + } + + // Check if configuration is loaded + if (!Config.isConfigLoaded()) { + throw new Error("ERROR : contract key configuration has to be loaded to load Geoportal layers. See http://ignf.github.io/evolution-apigeoportail/ol3/ol3-autoconf.html"); + } + + var layerId = Config.getLayerId(options.layer, "WMS"); + + if (layerId && Config.configuration.getLayerConf(layerId)) { + var config = {}; + var wmsParams = Config.getLayerParams(options.layer, "WMS", options.apiKey); + + if (wmsParams.projection === "EPSG:3857" && wmsParams.extent) { + wmsParams.extent = new ItExtent("EPSG:4326", wmsParams.extent.left, wmsParams.extent.right, wmsParams.extent.bottom, wmsParams.extent.top).as("EPSG:3857"); + } else { + wmsParams.extent = new ItExtent("EPSG:4326", wmsParams.extent.left, wmsParams.extent.right, wmsParams.extent.bottom, wmsParams.extent.top); + } + + // si ssl = false on fait du http + // par défaut, ssl = true, on fait du https + var protocol = options.ssl === false ? "http://" : "https://"; + + config.id = layerId; + config.source = new ItWMSSource({ + protocol : "wms", + version : wmsParams.version, + attribution : wmsParams.originators, + url : wmsParams.url.replace(/(http|https):\/\//, protocol), + name : options.layer, + projection : wmsParams.projection, + style : "", + heightMapWidth : 256, + waterMask : false, + networkOptions : { + crossOrigin : "omit" + }, + updateStrategy : { + type : 0, + options : {} + }, + format : wmsParams.format, + extent : { + west : wmsParams.extent.west, + east : wmsParams.extent.east, + south : wmsParams.extent.south, + north : wmsParams.extent.north + } + }); + + // ajout du tag gp-itowns-ext dans les requêtes WMS + config.source.url = Gp.Helper.normalyzeUrl(config.source.url, { + "gp-itowns-ext" : Pkg.itownsExtVersion || Pkg.version + }, false); + + // récupération des autres paramètres passés par l'utilisateur + Utils.mergeParams(config, options.itownsParams); + + // add legends and metadata (to be added to LayerSwitcher control) + config.legends = wmsParams.legends; + config.metadata = wmsParams.metadata; + config.description = wmsParams.description; + config.title = wmsParams.title; + config.quicklookUrl = wmsParams.quicklookUrl; + + return new ItColorLayer(config.id, config); + } else { + // If layer is not in Gp.Config + logger.error("ERROR layer id (layer name: " + options.layer + " / service: WMS ) was not found !?"); + } +} + +/* + * Constructor (alias) + */ +LayerWMS.prototype.constructor = LayerWMS; + +export default LayerWMS; diff --git a/src/Itowns-review/Layer/LayerWMTS.js b/src/Itowns-review/Layer/LayerWMTS.js new file mode 100644 index 000000000..d068a13ba --- /dev/null +++ b/src/Itowns-review/Layer/LayerWMTS.js @@ -0,0 +1,129 @@ +import Gp from "geoportal-access-lib"; +import Utils from "../../Common/Utils"; +import Config from "../../Common/Utils/Config"; +import Logger from "../../Common/Utils/LoggerByDefault"; +import Pkg from "../../../package.json"; +import { + Extent as ItExtent, + WMTSSource as ItWMTSSource, + ColorLayer as ItColorLayer +} from "itowns"; +/* import Extent from "itowns/Core/Geographic/Extent"; +import WMTSSource from "itowns/Source/WMTSSource"; +import ColorLayer from "itowns/Layer/ColorLayer"; */ + +var logger = Logger.getLogger("wmtsLayer"); + +/** + * @classdesc + * Geoportal WMTS source creation + * + * @constructor + * @alias itowns.layer.GeoportalWMTS + * @param {Object} options - options for function call. + * @param {String} options.layer - Layer name (e.g. "ORTHOIMAGERY.ORTHOPHOTOS") + * @param {Boolean} [options.ssl = true] - use of ssl or not (default true, service requested using https protocol) + * @param {String} [options.apiKey] - Access key to Geoportal platform + * @param {Object} [options.itownsParams] - other options for itowns.GlobeView.addLayer function (see {@link http://www.itowns-project.org/itowns/API_Doc/GlobeView.html#addLayer GlobeView.addLayer}) + * @example + * var geoportalWMTS = new itowns.layer.GeoportalWMTS({ + * layer : "ORTHOIMAGERY.ORTHOPHOTOS" + * }); + */ +function LayerWMTS (options) { + if (!(this instanceof LayerWMTS)) { + throw new TypeError("ERROR CLASS_CONSTRUCTOR"); + } + + // check layer params + if (!options.layer) { + throw new Error("ERROR PARAM_MISSING : layer"); + } + if (typeof options.layer !== "string") { + throw new Error("ERROR WRONG TYPE : layer"); + } + + // par defaut + if (typeof options.ssl === "undefined") { + options.ssl = true; + } + + // Check if configuration is loaded + if (!Config.isConfigLoaded()) { + throw new Error("ERROR : contract key configuration has to be loaded to load Geoportal layers. See http://ignf.github.io/evolution-apigeoportail/ol3/ol3-autoconf.html"); + } + + var layerId = Config.getLayerId(options.layer, "WMTS"); + + if (layerId && Config.configuration.getLayerConf(layerId)) { + var config = {}; + var wmtsParams = Config.getLayerParams(options.layer, "WMTS", options.apiKey); + + if (wmtsParams.projection === "EPSG:3857" && wmtsParams.extent) { + wmtsParams.extent = new ItExtent("EPSG:4326", wmtsParams.extent.left, wmtsParams.extent.right, wmtsParams.extent.bottom, wmtsParams.extent.top).as("EPSG:3857"); + } else { + wmtsParams.projection = "EPSG:4326"; + wmtsParams.extent = new ItExtent("EPSG:4326", wmtsParams.extent.left, wmtsParams.extent.right, wmtsParams.extent.bottom, wmtsParams.extent.top); + } + + if (Object.entries(wmtsParams.tileMatrixSetLimits).length === 0 && wmtsParams.tileMatrixSetLimits.constructor === Object) { + wmtsParams.tileMatrixSetLimits = undefined; + } + + // si ssl = false on fait du http + // par défaut, ssl = true, on fait du https + var protocol = options.ssl === false ? "http://" : "https://"; + + config.id = layerId; + config.source = new ItWMTSSource({ + protocol : "wmts", + url : wmtsParams.url.replace(/(http|https):\/\//, protocol), + networkOptions : { + crossOrigin : "omit" + }, + updateStrategy : { + type : 0, + options : {} + }, + projection : wmtsParams.projection, + attribution : wmtsParams.originators, + name : options.layer, + format : wmtsParams.format, + tileMatrixSet : wmtsParams.TMSLink, + tileMatrixSetLimits : wmtsParams.tileMatrixSetLimits, + extent : { + west : wmtsParams.extent.west, + east : wmtsParams.extent.east, + south : wmtsParams.extent.south, + north : wmtsParams.extent.north + } + }); + + // ajout du tag gp-itowns-ext dans les requêtes WMTS + config.source.url = Gp.Helper.normalyzeUrl(config.source.url, { + "gp-itowns-ext" : Pkg.itownsExtVersion || Pkg.version + }, false); + + // récupération des autres paramètres passés par l'utilisateur + Utils.mergeParams(config, options.itownsParams); + + // add legends and metadata (to be added to LayerSwitcher control) + config.legends = wmtsParams.legends; + config.metadata = wmtsParams.metadata; + config.description = wmtsParams.description; + config.title = wmtsParams.title; + config.quicklookUrl = wmtsParams.quicklookUrl; + + return new ItColorLayer(config.id, config); + } else { + // If layer is not in Gp.Config + logger.error("ERROR layer id (layer name: " + options.layer + " / service: WMTS ) was not found !?"); + } +} + +/* + * Constructor (alias) + */ +LayerWMTS.prototype.constructor = LayerWMTS; + +export default LayerWMTS; diff --git a/src/Itowns-review/Layer/VectorTileLayer.js b/src/Itowns-review/Layer/VectorTileLayer.js new file mode 100644 index 000000000..0392bd864 --- /dev/null +++ b/src/Itowns-review/Layer/VectorTileLayer.js @@ -0,0 +1,89 @@ +import Logger from "../../Common/Utils/LoggerByDefault"; +import Config from "../../Common/Utils/Config"; + +import { + VectorTilesSource as ItVectorTilesSource, + ColorLayer as ItColorLayer +} from "itowns"; +/* import Extent from "itowns/Core/Geographic/Extent"; +import WMSSource from "itowns/Source/WMSSource"; +import ColorLayer from "itowns/Layer/ColorLayer"; */ + +var logger = Logger.getLogger("vectorTileLayer"); + +/** + * @classdesc + * Geoportal WMTS source creation + * + * @constructor + * @private + * @alias itowns.layer.VectorTileLayer + * @param {Object} options - options for function call. + * @param {String} options.id - id to give to the layer + * @param {String} options.layer - Layer name (e.g. "PLAN.IGN") + * @param {String} [options.url] - Url to the vector Tile json style + * @param {String} [options.urlService] - Url to the pbf file. Retrieved in the style file by default. + * @param {Function} [options.filter] - Filter applied to the vector layer style. Fill/Line layer type by default. + * @param {Object} [options.attributions] - Attributions of the layer. + * @param {Object} [options.zoom] - Between which zoom levels the layer is displayed (zoom.min and zoom.max) + * @example + * var vectorTileLayer = new itowns.layer.VectorTileLayer({ + * layer : "PLAN.IGN" + * }); + */ +function VectorTileLayer (options) { + if (!(this instanceof VectorTileLayer)) { + throw new TypeError("ERROR CLASS_CONSTRUCTOR"); + } + + // check layer params + if (!options.layer) { + throw new Error("ERROR PARAM_MISSING : layer"); + } + if (typeof options.layer !== "string") { + throw new Error("ERROR WRONG TYPE : layer"); + } + + // Check if configuration is loaded + if (!Config.isConfigLoaded()) { + throw new Error("ERROR : contract key configuration has to be loaded to load Geoportal layers. See http://ignf.github.io/evolution-apigeoportail/ol3/ol3-autoconf.html"); + } + + var layerId = Config.getLayerId(options.layer, "TMS"); + + if (layerId && Config.configuration.getLayerConf(layerId)) { + var config = {}; + var tmsParams = Config.getLayerParams(options.layer, "TMS", options.apiKey); + + // si ssl = false on fait du http + // par défaut, ssl = true, on fait du https + var protocol = options.ssl === false ? "http://" : "https://"; + + config.id = layerId; + + config.source = new ItVectorTilesSource({ + style : tmsParams.url.replace(/(http|https):\/\//, protocol), + url : options.urlService, + attribution : options.attributions, + filter : options.filter || function (layer) { return ["fill", "line"].includes(layer.type); }, + zoom : options.zoom + }); + + // FIXME wait for next itowns release to remove this + config.isValidData = function () { + return false; + }; + + return new ItColorLayer(config.id, config); + } else { + // If layer is not in Gp.Config + logger.error("ERROR layer id (layer name: " + options.layer + " / service: TMS ) was not found !?"); + } +}; + +/* + * Constructor (alias) + */ +VectorTileLayer.prototype.constructor = VectorTileLayer; + +export default VectorTileLayer; diff --git a/src/Itowns-review/Styles.js b/src/Itowns-review/Styles.js new file mode 100644 index 000000000..a612d3d88 --- /dev/null +++ b/src/Itowns-review/Styles.js @@ -0,0 +1,7 @@ +import "./CSS/GPgeneralWidgetItowns.css"; +import "./CSS/Controls/Attribution/GPattributionItowns.css"; +import "./CSS/Controls/BoostRelief/GPboostReliefItowns.css"; +import "./CSS/Controls/LayerSwitcher/GPlayerSwitcherItowns.css"; +import "./CSS/Controls/MiniGlobe/GPminiGlobeItowns.css"; +import "./CSS/Controls/MousePosition/GPmousePositionItowns.css"; +import "./CSS/Controls/Scale/GPscaleItowns.css"; diff --git a/src/Itowns-review/index.js b/src/Itowns-review/index.js new file mode 100644 index 000000000..16cb27210 --- /dev/null +++ b/src/Itowns-review/index.js @@ -0,0 +1,151 @@ +/** +* Global variable Gp. +* +* @module Gp +* @alias Gp +* @desc +* +* This is the global variable that is exposed in the browser environment. +* Content is composed of constructor, functions and properties... +* +* > Config: (...) +* +* > ColorUtils: (...) +* > LayerUtils: (...) +* > MathUtils: (...) +* > ProxyUtils: (...) +* +* > itownsExtended: (...) +* +* > itownsExtVersion: "YYYY-MM-DD" +* > itownsExtVersion: "X.X.X" +* +* > Error: (...) +* > Helper: (...) +* > Protocols: (...) +* > Services: (...) +* > servicesDate: "YYYY-MM-DD" +* > servicesVersion: "X.X.X" +* +* The following variables are aslo global : +* - proj4, +* - itowns +*/ + +import Pkg from "../../package.json"; + +// CSS communes aux extensions ! +import "../Common/Styles"; +import "./Styles"; + +import MousePosition from "./Controls/MousePosition"; +import LayerSwitcher from "./Controls/LayerSwitcher"; +import BoostRelief from "./Controls/BoostRelief"; +import Attributions from "./Controls/Attributions"; +import Scale from "./Controls/Scale"; +import MiniGlobe from "./Controls/MiniGlobe"; +import GeoportalWMTS from "./Layer/LayerWMTS"; +import GeoportalWMS from "./Layer/LayerWMS"; +import GeoportalElevation from "./Layer/LayerElevation"; +import VectorTileLayer from "./Layer/VectorTileLayer"; +import GlobeViewExtended from "./GlobeViewExtended"; + +import CRS from "./CRS/CRS"; + +// Autoload... +import "../Common/Utils/AutoLoadConfig"; + +// export des services +import Gp from "geoportal-access-lib"; + +// reconstruction des ns +var Services = Gp.Services; +var Error = Gp.Error; +var Helper = Gp.Helper; +var Protocols = Gp.Protocols; +var servicesDate = Gp.servicesDate; +var servicesVersion = Gp.servicesVersion; + +export { + /** Services + * @see {@link http://ignf.github.io/geoportal-access-lib/current/jsdoc/module-Services.html|geoportal-access-lib} + */ + Services, + /** Error + * @see {@link http://ignf.github.io/geoportal-access-lib/current/jsdoc/Gp.Error.html|geoportal-access-lib} + */ + Error, + /** Helper + * @see {@link http://ignf.github.io/geoportal-access-lib/current/jsdoc/module-Helper.html|geoportal-access-lib} + */ + Helper, + /** Protocols + * @see {@link http://ignf.github.io/geoportal-access-lib/current/jsdoc/module-XHR.html|geoportal-access-lib} + */ + Protocols, + /** servicesDate + * @see {@link http://ignf.github.io/geoportal-access-lib/current/jsdoc/module-Gp.html|geoportal-access-lib} + */ + servicesDate, + /** servicesVersion + * @see {@link http://ignf.github.io/geoportal-access-lib/current/jsdoc/module-Gp.html|geoportal-access-lib} + */ + servicesVersion +}; + +// Adds the extensions properties in the namespace +export { default as LayerUtils } from "../Common/Utils/LayerUtils"; +export { default as ProxyUtils } from "../Common/Utils/ProxyUtils"; +export { default as ColorUtils } from "../Common/Utils/ColorUtils"; +export { default as MathUtils } from "../Common/Utils/MathUtils"; + +function deepCopy (source, target) { + // Implementing Tail Call Elimination + function tce (source, target) { + for (var prop in source) { + if (source.hasOwnProperty(prop)) { + if (!target.hasOwnProperty(prop)) { + target[prop] = source[prop]; + } else if (typeof source[prop] === "object") { + tce(source[prop], target[prop]); + } + } + } + } + return tce(source, target); +} + +// Adds extensions properties in the namespace +/** Version */ +export const itownsExtVersion = Pkg.itownsExtVersion; +/** Publication date */ +export const itownsExtDate = Pkg.date; + +// creation of the namespace for the itowns extensions +var Itowns = {}; +Itowns.control = {}; +Itowns.control.MousePosition = MousePosition; +Itowns.control.LayerSwitcher = LayerSwitcher; +Itowns.control.BoostRelief = BoostRelief; +Itowns.control.Attributions = Attributions; +Itowns.control.Scale = Scale; +Itowns.control.MiniGlobe = MiniGlobe; +Itowns.layer = {}; +Itowns.layer.GeoportalWMTS = GeoportalWMTS; +Itowns.layer.GeoportalWMS = GeoportalWMS; +Itowns.layer.GeoportalElevation = GeoportalElevation; +Itowns.layer.VectorTileLayer = VectorTileLayer; +Itowns.CRS = CRS; +Itowns.GlobeViewExtended = GlobeViewExtended; + +export { + /** Expose extensions extended */ + Itowns as itownsExtended +}; + +// Expose extensions extended into itowns +if (window.itowns) { + // on fusionne les fonctionnalités o + deepCopy(Itowns, window.itowns); + deepCopy(window.itowns, Itowns); +}