Issue With Collapse component when custom code exists

Hello everyone,

I have a fairly complex form which I am developing. It will host a dashboard with charts one tab 1, tab 2 contains details, and tab 3 will have various reports the user will be able to execute and download results.

Since all of these features require filtering, I decided to use the Collapse control to hide the numerous fields needed for user criteria. I had no issue adding the controls and the various labels and inputs. When I try to execute the "Show" button does just that and shows the details, correctly moving the content, which is below it lower on the page. When I go to collapse, it does nothing. I created a dummy project and could not get it to fail. Next, I started a test project, copied the page from the "real" project, and used the process of elimination to find out what was causing it to fail.

The failure occurs because of Custom Code, which is required to load external scripts (see my other posts about including custom JScript code includes for a specific paging - I sincerely HOPE this feature is coming in the next release.) If I remove the Custom Code, which loads jquery, bootstrap, aos, and my custom javascript, the Collapse control works. If I add it back, it fails to collapse the content.

I added a test project to jsfiddle for those of you who would like to take a peek. Perhaps there is something wrong I am not seeing? Of course, I could not upload all of the code or give access to data for this project.

https://jsfiddle.net/BKimFromColumbus/7jtu6mod/2/

Click the Show Content button to expand, and again. You will see it does not collapse.

In addition, it would be nice if BStudio would add code to switch the text (as an option) when the content is collapsed vs. shown.

Any assistance would be much appreciated!

Ben

Well to make it work you could start by removing the Bootstrap and AOS in the body. It should work then. I guess I dont understand why the script is in the body ? Why not put it last underneath all the rest at the end since its a onload type script and just needs jquery anyway ?

Brilliant! Thank you. That worked! JQuery was required for this instance so I am not sure why I copied the other two js libraries.

I still am holding out hope that the author of BStudio will allow us to include JS files on a per page basis. For example, I use Chart.js but only on a handful of the dozens of pages I developed thus far. I also use Tabulator for table definitions but only on select maintenance forms. If this feature were added it would allow for cleaner generated code and developers would not have to "clean up" the extra JS includes after exporting or publishing.

Thanks again Twinstream! Have a wonderful evening.

Ben

If you use this small script loader function loadJS you can probably accomplish what you want using a "conditional if statement" wrapping each group.

https://github.com/filamentgroup/loadJS Use Link External JS

Then create another script loadJSsettings and put this in...

if ($("body").hasClass("home")) {
    loadjs("https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js", true);
    loadjs("https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js", true);
    loadjs("https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js", function() {
        console.log("All Scripts Loaded");
    }, true);
}

Add the class "home" to the body. Now the only way this script will run is if the body has class "home".

Just start adding more if statements for the other pages with new class names.

Since the script loads after jquery any of your scripts depending on jquery will work too.

Oddly, your suggestion did not work. I added a div with a class name of home in the body directly, the parent of this div is body as shown below. I attempted to wrap the loader in a document ready function also. The alert I added never fires. Before I added the Alert, I also tried setting the defer option to false to see if that would work.

The load order in bootstrap studio is:

  1. jquery.min.js
  2. bootstrap.min.js
  3. loadjs.js
  4. nibrs_header_loader.js (code is listed below)

Code Listing of nibrs_header_loader.js

$(document).ready(function() {
    alert("before if body"); // This FIRES   
    if ($("body").hasClass("home")) {
        alert("found nibrs_header"); // This does not Fire
        loadjs("https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js", true);
        loadjs("https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js", true);
        loadjs("https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js", true);
        loadjs("http://vm-win10-05:8080/js/tabulator_core.min.js", true);
        loadjs("http://vm-win10-05:8080/js/tabulator.js", true);
        loadjs("http://vm-win10-05:8080/js/tabulator.min.js", true);

        loadjs("http://vm-win10-05:8080/js/nibrsHeader.js", true);
        loadjs("http://vm-win10-05:8080/js/chartjs_test.js", true);
        loadjs("http://vm-win10-05:8080/js/chartjs_test2.js", function() {
                console.log("All Scripts Loaded");
        }, true);
    }
});

HTML Snippet showing div with class of home

  <!DOCTYPE html> <html>
     <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
        <title>NIBRS Submission</title>
        <link rel="stylesheet" href="/bootstrap/css/bootstrap.min.css">
        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Cookie">
        <link rel="stylesheet" href="/fonts/fontawesome-all.min.css">
        <link rel="stylesheet" href="/fonts/font-awesome.min.css">
        <link rel="stylesheet" href="/fonts/fontawesome5-overrides.min.css">
        <link rel="stylesheet" href="/Login-Form-Clean.css">
        <link rel="stylesheet" href="/Navigation-with-Search.css">
        <link rel="stylesheet" href="/Pretty-Footer.css">
        <link rel="stylesheet" href="/styles.css">
        <link rel="stylesheet" href="/Footer-Basic.css">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/aos/2.1.1/aos.css">
        <link rel="stylesheet" href="/tabulator.min.css">
     </head>
     <body>
        <div class="home"></div>
        <nav class="navbar navbar-light navbar-expand-md bg-info navigation-clean-search">
     ...

Any ideas why this wouldn't work?

I also ran the debugger in Firefox watching the console and Debugger windows. Nothing out of the ordinary happens with the exception the if ($("body").hasClass("home")) obviously is somehow failing.

Ben

Well the class home is on the <div> tag not the <body> tag

Either move the class home up to the body tag or change the script to look for it on the div

if ($("div").hasClass("home")) {

I found the answer on JQuery .hasClass()

I added an ID to the DIV and now JQuery finds the class by DIV ID. Everything is working as expected! Thank you again. Now I can create custom JS and apply to specific pages only or only load Chart.js when necessary. I am going to play around to see if I can use Has to find a specific element ID (i.e. HasId) instead of using Class...

With that said, it would be nice if BootStrap Studio allowed for Page Level artifacts for JS and perhaps Styles, Fonts, and Images too.

Thanks again for your assistance!

Ben

Correction, the charts are not showing up. Tabulator fills the data just fine. I am getting a TypeError for Chart.js

TypeError

Use of Mutation Events is deprecated. Use MutationObserver instead. aos.js:162:11
Layout Error - invalid mode set, defaulting to 'fitData' : fitDataStretch tabulator.min.js:5:13425
TypeError: item is null Chart.bundle.js:7743:14
TypeError: item is null Chart.bundle.js:7743:14
All Scripts Loaded nibrs_header_loader.js:13:21
jQuery.Deferred exception: $(...).mask is not a function @http://vm-win10-05:8080/js/nibrsHeader.js:121:22
e@http://192.168.0.65:8000/js/jquery-3.4.1.min.js:2:29453
l/</t<@http://192.168.0.65:8000/js/jquery-3.4.1.min.js:2:29755
 undefined jquery-3.4.1.min.js:2:31008
TypeError: $(...).mask is not a function nibrsHeader.js:121:22

I dont think you will be able to link to any local js files. They will all have to be uploaded and the link references updated unless you plan on using a local server for testing and include the folder for the additional js files.

I would remove one of the chart.bundle as I was just using two for demo purposes.

Unfortunately, regardless of what I try, I am still getting errors on Chart.js. For the time being, I am just going to leave these as direct imports in BootStrap Studio and hope the developer of this tool adds the feature requested by me and others. I still believe there needs to be Global includes but the import by page for CSS, JS, Fonts, and Images option would be invaluable!

Ben

I was able to make it work but you cannot use the Chart component. You have to use Custom Code for the canvas div.

I followed the example on the website for Chart.js

<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3],
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255, 99, 132, 1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero: true
                }
            }]
        }
    }
});
</script>

The canvas goes is the custom code div. You then use the loadJS to load the cdn for chart.js and then you must link to the script that contatins the settings below the canvas also using loadJS.

Example

https://charted.bss.design/index.html

Thank you for your example. I had it working as you stated much earlier in this post but I would like to not put a bandaid on the issue if it can be resolve with a new feature.

I do appreciate you assistance and guidance though!

Ben

If working with the js data local inside Bootstrap Studio is needed then a <svg> does allow scripting.

https://johnnydepp.bss.design/

Actually if the you want to add a script that requires jquery to only one page you can use a simple check with javascript to check to see if jquery has loaded before running the script. I removed the svg tag and I am only using a script inside the custom code component which could be located at the last of the page. This places the script tag right above the jquery script tag and keeps things tidy too. You can mangle the script also if you want faster load times.

https://johnnydepp.bss.design/

@Twinstream - The link you provided gives a 404 error - not found. Would you please jsfiddle the site code so I may examine?

Thank you!

Ben

As there are multiple methods to use, this one checks to see if jquery is loaded, then runs whatever is inside. In this case I am using getscript chart.js and then in the callback when completed running the chart data script inside that. I am using a custom code component with script tags.

https://johnnydepp.bss.design/index.html

Code to check for jquery

function checkVariable(){
   if ( window.jQuery){
      Do your jquery stuff here
   }
   else{
      window.setTimeout("checkVariable();",100);
   }
}
checkVariable();