Dynamic KPI Cards in Oracle APEX: Editable, Resizable, Draggable, and Color-Changing Cards

 



 




JavaScript  File URLS:

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

Function and Global Variable Declaration:


$(document).ready(function () {
    function updateCardColors(color) {
        // Update the background color and text color for all cards
        $(".t-Card").css('background-color', color);
        $(".t-Card-body, .t-Card-wrap").css('color', color);
    }

    /***********Card funtionality ***************************** */
    // Enable drag-and-drop functionality for cards
    $(".t-Cards-item").draggable({
        containment: ".t-Cards-container", // Specify the containment area
        stack: ".t-Cards-item",
        cursor: "move",
    });
    // Enable card text editing
    $(".t-Card-desc").on("dblclick", function () {
        $(this).attr("contenteditable", "true").focus();
    }).on("blur", function () {
        $(this).removeAttr("contenteditable");
    });
    // Enable card coloring with a single color picker
    $(".color-input").on("input", function () {
        var selectedColor = $(this).val();
        updateCardColors(selectedColor);
    });
    // Initialize resizable behavior on the parent container
    $(".t-Cards").resizable({
        handles: "se", // Only enable resizing from the bottom-right corner
        minWidth: 300, // Set the minimum width
        minHeight: 200, // Set the minimum height
        start: function(event, ui) {
            $(this).addClass("resizing");
        },
        stop: function(event, ui) {
            $(this).removeClass("resizing");
            // Get the new width and height of the parent container
            var newWidth = ui.size.width;
            var newHeight = ui.size.height;
        
        },
    });
    // Handle scrollbar visibility on mouse enter and leave
    $(".t-Cards-container").mouseenter(function() {
        // Show scrollbars on mouse enter when resizing is active
        if ($(this).hasClass("resizing")) {
            $(this).css("overflow", "auto");
        }
    }).mouseleave(function() {
        // Hide scrollbars on mouse leave
        if ($(this).hasClass("resizing")) {
            $(this).css("overflow", "hidden");
        }
    })
  });


Inline css:


.t-Cards--basic .t-Card-title, .t-Cards--compact .t-Card-title {
    margin: 7px;
    overflow: hidden;
    text-overflow: ellipsis;
}


/* Style the t-Card to have a full-width */
.t-Card {
    width: 100%;
    background-color: #FFFFFF; /* Set your desired background color here */
    border: 1px solid #E0E0E0; /* Add a border if needed */
    box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); /* Add shadow if desired */
}
/* Style the t-Card-wrap for centering */
.t-Card-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 20px; /* Add padding as needed */
}
/* Style the t-Card-color-picker to be in the upper-right corner */
.t-Card-color-picker {
    position: absolute;
    top: 10px; /* Adjust top position as needed */
    right: 10px; /* Adjust right position as needed */
}
/* Style the t-Card-title */
.t-Card-title {
    font-size: 24px; /* Set your desired font size */
    color: #000000; /* Set your desired font color */
    margin: 10px 0; /* Add margin as needed */
}
/* Style the t-Card-desc */
.t-Card-desc {
    font-size: 18px; /* Set your desired font size */
    color: #333333; /* Set your desired font color */
    margin: 10px 0; /* Add margin as needed */
}

.t-Card {
    display: flex !important;
    flex-direction: column; /* Stack elements vertically */
    justify-content: center !important;
    align-items: center !important;
    align-content: center !important;
    gap: 10px !important;
    align-self: stretch !important;
    flex-wrap: wrap !important;
    color: #002E5D !important;
    text-align: center !important;
    font-family: 'Open Sans' !important;
    font-size: 24px !important;
    font-style: normal !important;
    font-weight: 600 !important;
    line-height: 28px !important;
    position: relative; /* Needed for positioning the color picker */
}
.t-Card-body {
    position: relative; /* Needed for positioning the color picker */
}
.t-Card-title {
    text-align: center; /* Center-align the title */
}
.t-Card-color-picker {
    position: absolute;
    top: 5px; /* Adjust the distance from the top */
    right: 5px; /* Adjust the distance from the right */
}


SQL Query:


WITH kpi_data AS (
    SELECT
        '10' AS card_title,
        TO_CHAR(DBMS_RANDOM.VALUE(10, 20)) AS random_number,
        'Median Enrollment Period (months)' AS card_text
    FROM DUAL
    UNION ALL
    SELECT
        '20' AS card_title,
      
        TO_CHAR(DBMS_RANDOM.VALUE(10, 20)) AS random_number,
        'Median Number of Sites per Trial' AS card_text
    FROM DUAL
    UNION ALL
    SELECT
        '30' AS card_title,
        
        TO_CHAR(DBMS_RANDOM.VALUE(10, 20)) AS random_number,
        'Median Enrollment Period (months)' AS card_text
    FROM DUAL
    UNION ALL
    SELECT
        '40' AS card_title,
       
        TO_CHAR(DBMS_RANDOM.VALUE(10, 20)) AS random_number,
        'Median Enrollment Rate (p/s/m)' AS card_text
    FROM DUAL
    UNION ALL
    SELECT
        '50' AS card_title,
        
        TO_CHAR(DBMS_RANDOM.VALUE(10, 20)) AS random_number,
        'Median Number of Sites per Trial' AS card_text
    FROM DUAL
    UNION ALL
    SELECT
        '60' AS card_title,
        
        TO_CHAR(DBMS_RANDOM.VALUE(10, 20)) AS random_number,
        'Number of Benchmark Trials' AS card_text
    FROM DUAL
)
SELECT * FROM kpi_data;


Edit Card Template: 

1. Create a copy of the default card first and then used in classic report attribute section under templete

2. Paste This Template code into both  (Row Template 1, Row Template 2)  same


<li class="t-Cards-item #CARD_MODIFIERS#">

    <div class="t-Card">

        <div>

            <div class="t-Card-icon">

                <span class="t-Icon fa #CARD_ICON#">

                    <span class="t-Card-initials" role="presentation">#CARD_INITIALS#</span>

                </span>

            </div>

            <div class="t-Card-body">

                <h3 class="t-Card-title">#CARD_TITLE#</h3>

                <div class="t-Card-desc" contenteditable="true">#CARD_TEXT#</div>

            </div>

        </div>

    </div>

</li>




Classis report Static ID: kpi_card

Right Side filter column  HTML code:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Card Color Changer</title>
    <style>
        /* Your existing CSS styles */
        .color-pickers {
            display: flex;
            justify-content: center;
            gap: 20px;
            margin-bottom: 20px;
        }
        .color-picker {
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        label {
            margin-bottom: 5px;
            font-weight: bold;
        }
        .t-Card-container {
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
        }
        .t-Card {
            margin: 10px;
            padding: 10px;
            display: inline-block;
            border: 1px solid #ccc;
            border-radius: 5px;
        }
        .color-pickers {
    display: flex;
    flex-direction: column;
}
.color-picker {
    margin-bottom: 10px; /* Optional spacing between color pickers */
}
        .t-Card-title,
        .t-Card-desc {
            margin: 5px 0;
            padding: 0;
        }
    </style>
</head>
<body>
<div class="color-pickers">
    <div class="color-picker">
        <label for="bgColorPicker">Choose a background color:</label>
        <input type="color" id="bgColorPicker" value="#0076a5">
    </div>
    <div class="color-picker">
        <label for="textColorPicker">Choose a text color:</label>
        <input type="color" id="textColorPicker" value="#ffffff">
    </div>
</div>


    <div class="t-Card-container" id="cardContainer">
        <!-- Your cards go here -->
    </div>

    <select id="cardLayout">
        <option value="2x3">2x3 Card Layout</option>
        <option value="3x2">3x2 Card Layout</option>
    </select>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
        $(document).ready(function () {
            function updateCardColors(bgColor, textColor) {
                // Update the background color for all cards
                $(".t-Card").css('background-color', bgColor);
                // Update the text color for title and description
                $(".t-Card-title, .t-Card-desc").css('color', textColor);
            }
            // Function to create the default card template
            function createDefaultTemplate() {
                var $defaultCard = $("<div class='t-Card'><div><div class='t-Card-icon'><span class='t-Card-initials' role='presentation'>D</span></div><div class='t-Card-body'><h3 class='t-Card-title'>Default Title</h3><div class='t-Card-desc' contenteditable='true'>Default Text</div></div></div></div>");
                return $defaultCard;
            }
            // Initialize the color pickers with initial colors
            var initialBgColor = $("#bgColorPicker").val();
            var initialTextColor = $("#textColorPicker").val();
            updateCardColors(initialBgColor, initialTextColor);
            // Listen to changes in the background color picker
            $("#bgColorPicker").on("input", function () {
                var selectedBgColor = $(this).val();
                var selectedTextColor = $("#textColorPicker").val();
                updateCardColors(selectedBgColor, selectedTextColor);
            });
            // Listen to changes in the text color picker
            $("#textColorPicker").on("input", function () {
                var selectedBgColor = $("#bgColorPicker").val();
                var selectedTextColor = $(this).val();
                updateCardColors(selectedBgColor, selectedTextColor);
            });
            
            // Card layout change functionality
           
        });
    </script>
</body>
</html>


Stay Informed:  Stay up-to-date with the latest Oracle APEX tips and updates by following my social media profiles.

 Follow on YouTube:  Dive deeper into Oracle APEX by exploring my YouTube channel for tutorials and insights: 

 YouTube Channel: YouTube


Connect on LinkedIn:  Let's connect on LinkedIn for networking opportunities, discussions, and more: 

 LinkedIn Profile: Linkedin



 

Comments