Promoting a simple Oracle JET input text component to a Visual Country Selection component image 2

Promoting a simple Oracle JET input text component to a Visual Country Selection component

To select a country (or any other geographical entity), we can offer our end users a dropdown list, a list of values in a popup window, an auto suggest input text component or a more visual, map based approach. In this article, I describe the latter: Open a modal popup that presents a map of the world and allows the user to inspect and select a country. Note: this article is a logical extrapolation from previous articles on OpenLayers and Oracle JET, specifically this article.

This article demonstrates how we go from a simple input text component and extend it: with a background image (a little globe) that the user can click.

 

image

When the user clicks the icon, a popup opens and shows the world map. If the input component contains a valid country name, this country is selected in the map. The user can click on any country and in doing so, selects the country.

 

image

The name of the country is written back to the input text component (Mali in the next figure).

image

The main challenges discussed in this article:

Starting with the situation from the previous article (the third bullet overhead), this article describes how to create an input text component with clickable icon that opens a popup window that shows the map.

The final code is found here on GitHub: https://github.com/lucasjellema/jet-and-openlayers.

Embed the OpenLayers map in an Oracle JET Popup Component

This step is a simple one. I used the entry in the JET Cookbook on Popup Component: http://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html?component=popup&demo=modal. I copied the styles used in this example to the file src/css/app.css:

.demo-popup {
    width: 80vw;  
    height: 80vh; 
    display: none;
  } 
  .demo-popup-body {
    width: 75vw;  
    height: 75vh; 
    display: flex; 
    flex-direction: column;
    align-items: stretch;
  } 
  .demo-popup-header {
    align-self: flex-start;
    margin-bottom: 10px;
  } 
  .demo-popup-content {
    align-self: stretch;
    overflow: auto;
    flex-basis: 60vh;
  } 
  .demo-popup-footer {
    align-self: flex-end;
    margin-top: 10px; 
  } 

Next I added the popup component in the mapArea.html file, with the DIV that acts as the map container in

<div id="popupWrapper">
    <oj-popup class="demo-popup" id="countrySelectionPopup" tail="none" position.my.horizontal="center" position.my.vertical="bottom" position.at.horizontal="center"
        position.at.vertical="bottom" position.of="window" position.offset.y="-10" modality="modal" data-bind="event:{'ojAnimateStart': startAnimationListener}">
        <div class="demo-popup-body">
            <div class="demo-popup-header">
                <h5>Select a country by clicking on it</h5>
            </div>
            <div class="demo-popup-content">
                <div id="countryInfo"></div>
                <div id="mapContainer" class="map"></div>
            </div>
            <div class="demo-popup-footer">
                <oj-button id="btnClose" data-bind="click: function()
                            {
                              var popup = document.querySelector('#countrySelectionPopup');
                              popup.close();
                            }">
                    Close
                </oj-button>
            </div>
        </div>
    </oj-popup>
</div>

I added the function startAnimationListener to the ViewModel in mapArea.js:


            self.startAnimationListener = function (data, event) {
                var ui = event.detail;
                if (!$(event.target).is("#countrySelectionPopup"))
                    return;

                if ("open" === ui.action) {
                    event.preventDefault();
                    var options = { "direction": "top" };
                    oj.AnimationUtils.slideIn(ui.element, options).then(ui.endCallback);
                    // if the map has not yet been initialized, then do the initialization now (this is the case the first time the popup opens)
                    if (!self.map) initMap();
                }
                else if ("close" === ui.action) {
                    event.preventDefault();
                    ui.endCallback();
                }
            }

The initialization of the map is taken care of in open stage for the popup this startAnimationListener – on the first occasion this popup is opened.

 

Embed a clickable icon in an input text component to allow the end user to open the popup with a mouse click

It is important that the user has a convenient way of opening the country selection popup. Just like the date and time input components provide a little clickable icon, inline in the input component, I want the country selector to consist of a regular JET input text component with an inline icon that the user can click on to bring up the popup.

image

The HTML code to make this happen is added to mapArea.html:

    <div id="countryInput">
        <oj-label for="country-input">Country</oj-label>
        <oj-input-text id="country-input" value="{{selectedCountry}}" on-value-changed="[[countryChangedListener]]"
        ></oj-input-text>
        <img id="countrySelectorOpen" src="css/images/icon-world.png" class='iconbtnintext' title ="Click to open World Map in Popup" data-bind="click: openPopup" /> 
    </div>

Note how the click event on the image is bound to the KnockOut ViewModel’s openPopup function using the data-bind notation,

The CSS style iconbtnintext takes care of the positioning of the icon. This style is added to app.css:

.iconbtnintext {	
    position:absolute;
    cursor:pointer;
    width:22px;
    height:23px;
    margin-left:-24px;
    padding-top:4px;
}

Finally the icon to be used – icon-world.png – is copied to src/css/images

image

 

 

References

JET Cookbook on Popup Component: http://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html?component=popup&demo=modal