Focal Point
[RE-OPENED] Add select2 to HTML canvas

This topic can be found at:
https://forums.informationbuilders.com/eve/forums/a/tpc/f/7971057331/m/4707061096

May 15, 2018, 12:18 PM
Shingles
[RE-OPENED] Add select2 to HTML canvas
Hi All,

You folks have helped me tonnes, thank you.

As I've stated in other posts, I'm pretty new to WebFOCUS and I've inherited a lot of code.

I'm in a situation where I have an HTML file created via the HTML canvas. It has several controls. One of which is a drop down list box that has many values in it. We have had a request from multiple sources to change this control so that it is a little more manageable (the length is very long and it is frustrating to use it).

In a past life, I've used the select2.js library and I thought this should be a great place to use it. But I'm not sure if such a thing is even possible. I've read from a few other posts that people use it (select2), but I don't think it was used with the situation I'm in. To be more specific, I haven't read any instructions on how to use this library in HTML canvas. Does that even make sense, I hope so? My experience with HTML canvas has been frustrating (like adding a simple hyperlink), so I'm leery on this whole endeavor.

Thank you!

This message has been edited. Last edited by: Shingles,


WebFOCUS 8201, SP 0.1, Windows 7, HTML
May 15, 2018, 01:22 PM
Francis Mariani
Thank you for introducing me to Select2 - I hadn't come across it before.

From looking at the documentation, it appears all you need to do is:

- Reference the jQuery and select2 js libraries
- Reference the select2 CSS library
- Set the select box to a select2 class
- Set the select box as a select2 element using $( document ).ready()

This is a simple hand-coded example. The actions mentioned above are possible to do through the HTML Canvas GUI tool.

<!doctype html>

<html lang="en">

<head>
    <meta charset="utf-8">

    <title>Basic Select2 Example</title>

    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>

    <!--
        <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
        <link href="https://code.jquery.com/ui/1.11.4/themes/humanity/jquery-ui.css" rel="stylesheet" />
    -->

    <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />

    <script>
        $(document).ready(function() {
            $('.js-example-basic-single').select2();
        });
    </script>
</head>

<body>

    <select class="js-example-basic-single" style="width: 300px;">
        <optgroup label="Alaskan/Hawaiian Time Zone">
            <option value="AK">Alaska</option>
            <option value="HI">Hawaii</option>
        </optgroup>
        <optgroup label="Pacific Time Zone">
            <option value="CA">California</option>
            <option value="NV">Nevada</option>
            <option value="OR">Oregon</option>
            <option value="WA">Washington</option>
        </optgroup>
        <optgroup label="Mountain Time Zone">
            <option value="AZ">Arizona</option>
            <option value="CO">Colorado</option>
            <option value="ID">Idaho</option>
            <option value="MT">Montana</option>
            <option value="NE">Nebraska</option>
            <option value="NM">New Mexico</option>
            <option value="ND">North Dakota</option>
            <option value="UT">Utah</option>
            <option value="WY">Wyoming</option>
        </optgroup>
        <optgroup label="Central Time Zone">
            <option value="AL">Alabama</option>
            <option value="AR">Arkansas</option>
            <option value="IL">Illinois</option>
            <option value="IA">Iowa</option>
            <option value="KS">Kansas</option>
            <option value="KY">Kentucky</option>
            <option value="LA">Louisiana</option>
            <option value="MN">Minnesota</option>
            <option value="MS">Mississippi</option>
            <option value="MO">Missouri</option>
            <option value="OK">Oklahoma</option>
            <option value="SD">South Dakota</option>
            <option value="TX">Texas</option>
            <option value="TN">Tennessee</option>
            <option value="WI">Wisconsin</option>
        </optgroup>
        <optgroup label="Eastern Time Zone">
            <option value="CT">Connecticut</option>
            <option value="DE">Delaware</option>
            <option value="FL">Florida</option>
            <option value="GA">Georgia</option>
            <option value="IN">Indiana</option>
            <option value="ME">Maine</option>
            <option value="MD">Maryland</option>
            <option value="MA">Massachusetts</option>
            <option value="MI">Michigan</option>
            <option value="NH">New Hampshire</option>
            <option value="NJ">New Jersey</option>
            <option value="NY">New York</option>
            <option value="NC">North Carolina</option>
            <option value="OH">Ohio</option>
            <option value="PA">Pennsylvania</option>
            <option value="RI">Rhode Island</option>
            <option value="SC">South Carolina</option>
            <option value="VT">Vermont</option>
            <option value="VA">Virginia</option>
            <option value="WV">West Virginia</option>
        </optgroup>
    </select>

</body>

</html>



Francis


Give me code, or give me retirement. In FOCUS since 1991

Production: WF 7.7.05M, Dev Studio, BID, MRE, WebSphere, DB2 / Test: WF 8.1.05M, App Studio, BI Portal, Report Caster, jQuery, HighCharts, Apache Tomcat, MS SQL Server
May 15, 2018, 02:59 PM
Francis Mariani
An alternative is to use chained controls. For this example, the State control would be chained to the Time Zone control: select a Time Zone, see only the States for that Time Zone, then select the State.


Francis


Give me code, or give me retirement. In FOCUS since 1991

Production: WF 7.7.05M, Dev Studio, BID, MRE, WebSphere, DB2 / Test: WF 8.1.05M, App Studio, BI Portal, Report Caster, jQuery, HighCharts, Apache Tomcat, MS SQL Server
May 15, 2018, 03:04 PM
Shingles
Yes, I considered the chaining approach but that won't serve me well here.

I will try to implement select2 via the gui. Fingers crossed.

Thank you Francis...


WebFOCUS 8201, SP 0.1, Windows 7, HTML
May 16, 2018, 11:29 AM
Shingles
I've been able to bring the js and css files into html canvas. And I set the class of the drop down to select2 (internal_default gets appended). I'm not sure how to associate that control with select2 however.

I've tried many things... I think this got me the farthest... I've added the following js code (it is NOT wrapped in the window_onload function):
  
function onInitialUpdate() {
    $(document).ready(function() {
        $("#OfficerDropDown").addClass("select2"); //I don't think this is necessary, but it shouldn't hurt
        $("#OfficerDropDown").removeClass("internal_default");
        $("#OfficerDropDown").select2();
    });
}


The styling is changed, but the list doesn't have anything in it. Since it is empty I can't really test if it is using select2.js.

Any tips?

Thank you,

This message has been edited. Last edited by: Shingles,


WebFOCUS 8201, SP 0.1, Windows 7, HTML
May 16, 2018, 12:06 PM
Hallway
The only way that I was able to get the values in the dropdown, was by using jQuery:

  
function onInitialUpdate() {
   $(document).ready(function() {
      $('.js-example-basic-multiple').attr('multiple','multiple').select2({
         "data": [
            { 
               "text": "Alaskan/Hawaiian Time Zone", 
               "children" : [
                  {
                     "id": "AK",
                     "text": "Alaska"
                  },
                  {
                     "id": "HI",
                     "text": "Hawaii"
                  },
               ]
            },
            { 
               "text": "Pacific Time Zone", 
               "children" : [
                  {
                     "id": "CA",
                     "text": "California"
                  },
                  {
                     "id": "NV",
                     "text": "Nevada"
                  },
                  {
                     "id": "OR",
                     "text": "Oregon"
                  },
                  {
                     "id": "WA",
                     "text": "Washington"
                  },
               ]
            },
            { 
               "text": "Mountain Time Zone", 
               "children" : [
                     {
                        "id": "AZ",
                        "text": "Arizona"
                     },
                     {
                        "id": "CO",
                        "text": "Colorado"
                     },
                     {
                        "id": "ID",
                        "text": "Idaho"
                     },
                     {
                        "id": "MT",
                        "text": "Montana"
                     },
                     {
                        "id": "NE",
                        "text": "Nebraska"
                     },
                     {
                        "id": "NM",
                        "text": "New Mexico"
                     },
                     {
                        "id": "ND",
                        "text": "North Dakota"
                     },
                     {
                        "id": "UT",
                        "text": "Utah"
                     },
                     {
                        "id": "WY",
                        "text": "Wyoming"
                     },
                     ]
               },
         ],
         "closeOnSelect": false,
      }); 
   });
}


The above code initializes a multiselect that doesn't close on selection and is grouped by timezone.


Hallway

 
Prod: 8202M1
Test: 8202M4
Repository:
 
OS:
 
Outputs:
 
 
 
 
May 16, 2018, 12:26 PM
Shingles
Alright I figure it out... Everything seems to be working (this code is not in a wrapper, just on its own under the Embedded JavaScript tab).

   
function onInitialUpdate() {
   $("#OfficerDropDown").select2();
}


OfficerDropDown is the name and ID I gave the control in HTML canvas. The only thing that is a little wonky right now is that the drop box is in the top left corner of the container. Seems like none of the formatting in HTML canvas is respected.


WebFOCUS 8201, SP 0.1, Windows 7, HTML
May 16, 2018, 01:04 PM
Hallway
Oh, okay. I got it working. On thing that I noticed is that you CANNOT have the multiple attribute set to multiple in the WF GUI for it to populate the options.

If you inspect the page, you'll see that the original combobox, that was formatted in the HTML Cantvas, has been hidden and the combobox that you see is actually a span. You will need to style it using jQuery.


Hallway

 
Prod: 8202M1
Test: 8202M4
Repository:
 
OS:
 
Outputs:
 
 
 
 
May 16, 2018, 01:45 PM
Shingles
Oh good find. I'll not waste my time with formatting in HTML canvas then. Thank you!


WebFOCUS 8201, SP 0.1, Windows 7, HTML
May 16, 2018, 01:47 PM
Francis Mariani
quote:
Seems like none of the formatting in HTML canvas is respected.

I would make sure that any Dynamic Report Styling is turned OFF - BIP and/or HTML Canvas.

The populating of the select list shouldn't be affected by Select2. One day I'll give it a try in my ancient v8.1.05 environment.


Francis


Give me code, or give me retirement. In FOCUS since 1991

Production: WF 7.7.05M, Dev Studio, BID, MRE, WebSphere, DB2 / Test: WF 8.1.05M, App Studio, BI Portal, Report Caster, jQuery, HighCharts, Apache Tomcat, MS SQL Server
May 16, 2018, 02:07 PM
Hallway
Looking at the docs about labels for Select2, it looks like the select element needs to be the child of it's label. So I included a jQuery append method to move the select element inside the label before select2 is called. This aligns the dropdown right below the label.

  
function onInitialUpdate() {
   $(document).ready(function() {
      $('#label1').append($('#combobox1'));
      $('#combobox1').val(null).select2({
         closeOnSelect: false,
         multiple: true,
         placeholder: "- Make Selection(s) -",
         allowClear: true,
      }) ; 
   });
}


I also made it multi-select and changed the default selection to null along with giving it a placeholder telling the end user to make their selection(s).


Hallway

 
Prod: 8202M1
Test: 8202M4
Repository:
 
OS:
 
Outputs:
 
 
 
 
May 16, 2018, 02:37 PM
Shingles
That works perfectly... thank you!


WebFOCUS 8201, SP 0.1, Windows 7, HTML
May 16, 2018, 03:11 PM
Hallway
Glad to help. I learned a lot today as well.

Don't forget to mark the title with "[SOLVED]" if you don't have any further questions.


Hallway

 
Prod: 8202M1
Test: 8202M4
Repository:
 
OS:
 
Outputs:
 
 
 
 
May 17, 2018, 08:45 AM
Shingles
If I use the multiple select option it get a little wonky. I get delayed responses. I think it might have something to do with the length of the list.


WebFOCUS 8201, SP 0.1, Windows 7, HTML
May 25, 2018, 02:26 PM
Shingles
Hi Folks,
I'm having a couple of issues with the approach above. I have included the css and js files via the HTML canvas gui. And I included the following code in the Embedded JavaScript tab (it isn't wrapped in anything, or at least not in the Embedded JavaScript tab):
  
function onInitialUpdate() {

    $(document).ready(function() {
        $("#OffLabel").append($("#OffList"));
        $("#OffList").select2();
    });

}


The problem that I'm getting is that sometimes it appears that the select2.js library isn't applied. I suspect that select2 library hasn't yet been included, and so it can't find it. Any ideas here?

I've looked at this item that seems to be related, but this is also eight years old, so I'm not sure I should invest too much time into it. I'm also not sure how to modify the script tag (I would rather not modify the code of a htm file since HTML canvas may not play nice with it) as was suggested in that thread.

It shouldn't matter where the js or css files are right? I keep them in the Repository in a common folder.

EDIT: I've added some exception catching and I got this error message when it doesn't load: "Typeerror: object doesn't support property or method 'select2'". That tells me that my assumption is right... but I don't know how to fix it.

This message has been edited. Last edited by: Shingles,


WebFOCUS 8201, SP 0.1, Windows 7, HTML
May 25, 2018, 04:20 PM
Shingles
Hey Folks,
Ok... I think I figured it out...

I've added some exception handling. The exception happens only on the initial load. If the panel is refreshed then it doesn't. I borrowed some code from here.

I added this function to the embedded Javascript tab:
function loadScript(url, callback){
 
    var script = document.createElement("script")
    script.type = "text/javascript";
 
    if (script.readyState){  //IE
        script.onreadystatechange = function(){
            if (script.readyState == "loaded" ||
                    script.readyState == "complete"){
                script.onreadystatechange = null;
                callback();
            }
        };
    } else {  //Others
        script.onload = function(){
            callback();
        };
    }
 
    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}
  


And I modifed onInitialUpdate as follows:
 
function onInitialUpdate() {

    $(document).ready(function() {
        $("#OffLabel").append($("#OffList"));
        try {
            $("#OffList").select2();
        }
        catch(e) {   
            loadScript("https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js", function(){
                $("#OffList").select2();
            });
        }
    });

    $(".ui-dialog-title").empty(); //This line isn't necessary, its doing something else that isn't related with this thread
} 



WebFOCUS 8201, SP 0.1, Windows 7, HTML
May 28, 2018, 04:21 AM
Wep5622
Perhaps the issue is with your use of
$(document).ready(function() {
        $("#OffLabel").append($("#OffList"));
        $("#OffList").select2();
    });

As I read it, you're appending the same element back in without first removing it from its original position in the DOM. Quite possibly this duplicates the id of the element, causing possible conflicts on applying stuff to it depending on the order in which the browser finds the first matching element. That could explain the "randomness" you're experiencing.
I may be wrong, perhaps JQuery's .append makes sure to detach an existing element first, but I wouldn't bet on it...

Also, I'm pretty sure you can omit $(document).ready() when you're already initializing your code in onInitialUpdate(). AFAIK, that doesn't get called before the document is ready.


WebFOCUS 8.1.03, Windows 7-64/2008-64, IBM DB2/400, Oracle 11g & RDB, MS SQL-Server 2005, SAP, PostgreSQL 11, Output: HTML, PDF, Excel 2010
: Member of User Group Benelux :
May 28, 2018, 08:26 AM
Shingles
Thanks Wep,

First of all, my organization uses IE11, so I imagine some of the goofiness I see is a result of that.

I know what you mean about the $(document).ready bit, it doesn't seem necessary to me either. I tried the following code, but the htm panel never came back; the spinner never went away.
function onInitialUpdate() {
  //  $(document).ready(function() {
      //  $("#OffLabel").append($("#OffList"));
      //  try {
            $("#OffList").select2();
      //  }
      //  catch(e) {
            //"/WFC/Repository/Common/js/select2_min.js"
            //https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js     
      //      loadScript("/WFC/Repository/Common/js/select2_min.js", function(){
      //          $("#OffList").select2();
      //      });
      //  }
  //  });
    $(".ui-dialog-title").empty();
}  


Also, I don't think the append has anything to do with the randomness. I tried the following code, and the htm renders, but the select2 library wasn't applied.

function onInitialUpdate() {
    $(document).ready(function() {
      //  $("#OffLabel").append($("#OffList"));
      //  try {
            $("#OffList").select2();
      //  }
      //  catch(e) {
            //"/WFC/Repository/Common/js/select2_min.js"
            //https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js     
      //      loadScript("/WFC/Repository/Common/js/select2_min.js", function(){
      //          $("#OffList").select2();
      //      });
      //  }
    });
    $(".ui-dialog-title").empty();
}


So... I tried to remove the document.ready bit, and the append and both didn't have the desired results. The code I posted on May 25th seems to be working consistently, at least so far. If I do find any problems with it, I will post it here.


WebFOCUS 8201, SP 0.1, Windows 7, HTML
May 28, 2018, 11:30 AM
Wep5622
I was more thinking in the line of:

function onInitialUpdate() {
    $(document).ready(function() {
        var s2 = $("#OffList").detach(); // Make sure we're left with only one instance in the DOM

        $("#OffLabel").append(s2);
        try {
            $("#OffList").select2();
        }
        catch (e) { console.error("Danger Will Robinson!"); }
    });
    $(".ui-dialog-title").empty();



WebFOCUS 8.1.03, Windows 7-64/2008-64, IBM DB2/400, Oracle 11g & RDB, MS SQL-Server 2005, SAP, PostgreSQL 11, Output: HTML, PDF, Excel 2010
: Member of User Group Benelux :