{"id":138,"date":"2013-08-15T04:03:40","date_gmt":"2013-08-15T04:03:40","guid":{"rendered":"http:\/\/reichartonline.de\/?page_id=138"},"modified":"2025-01-11T22:39:35","modified_gmt":"2025-01-11T22:39:35","slug":"confirmation-boxes","status":"publish","type":"page","link":"https:\/\/reichartonline.de\/?page_id=138","title":{"rendered":"Confirmation Boxes"},"content":{"rendered":"<p><strong>Introduction<\/strong><\/p>\n<p>Confirmation boxes are definitely featured by any JavaScript framework. Nevertheless I was interested in learning what it took to implement configurable confirmation and decision boxes.<\/p>\n<div id=\"attachment_140\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/reichartonline.de\/content\/wp-content\/uploads\/2013\/08\/confirmation_box.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-140\" class=\"wp-image-140 size-medium\" src=\"http:\/\/reichartonline.de\/content\/wp-content\/uploads\/2013\/08\/confirmation_box-300x248.png\" alt=\"Confirmation Box\" width=\"300\" height=\"248\" srcset=\"https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2013\/08\/confirmation_box-300x248.png 300w, https:\/\/reichartonline.de\/content\/wp-content\/uploads\/2013\/08\/confirmation_box.png 687w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-140\" class=\"wp-caption-text\">Confirmation Box<\/p><\/div>\n<div><\/div>\n<p><strong>The HTML part<\/strong><\/p>\n<p>Just insert a hidden image to represent the box and a second one for the &#8220;curtain&#8221;. Such a curtain not only looks smart, but it avoids clicking on an element that should be protected while the page is dimmed.<\/p>\n<p>The box itself contains a division element that encapsulates a paragraph and the confirmation button.<\/p>\n<p>HTML<\/p>\n<pre lang=\"HTML\">&lt;img id=\"confirmation_box\" src=\"path_to_box_image\"&gt;\n&lt;img id=\"busy\" src=\"path_to_curtain_image\"&gt;\n\n&lt;div name=\"div_confirmation\" id=\"div_confirmation\"&gt;\n    &lt;p name=\"p_confirmation\" id=\"p_confirmation\"&gt;&lt;\/p&gt;\n    &lt;input type=\"button\" name=\"button_confirmation\" id=\"button_confirmation\" value=\"Continue\" onclick=\"javascript:FadeOutElement( 'div_confirmation' );\"&gt;\n&lt;\/div&gt;<\/pre>\n<p>Generating this code using your preferred language, captions, titles etc. may be set to variable values e.g. to enable national language support.<\/p>\n<p><strong>The CSS part<\/strong><\/p>\n<p>On page load, both images are hidden by setting full transparency (no opacity). To avoid any interference with visible elements, place the images below other elements (z-index -1). The opacity transition causes the element to fade in or out within 300 milliseconds.<\/p>\n<p>The division takes some more initial styling with sizing, borders and shadow.<\/p>\n<p>CSS<\/p>\n<pre lang=\"CSS\">img.dimmer\n{\n    position: absolute;\n    z-index: -1;\n    opacity: 0;\n    transition: opacity 0.3s linear;\n}\n\ndiv.confirmation\n{\n    z-index: 60;\n    position: absolute;\n    width: 200px;\n    height: 80px;\n    background-color: #FFFFFF;\n    padding: 10px;\n    text-align: center;\n    white-space: pre-wrap;\n    border-top: 2px solid silver;\n    border-bottom: 2px solid silver;\n    border-left: 2px solid silver;\n    border-top-left-radius: 10px;\n    border-top-right-radius: 10px;\n    border-bottom-left-radius: 10px;\n    border-bottom-right-radius: 10px;\n    box-shadow: 10px 10px 5px #888;\n    visibility: hidden;\n    opacity: 0;\n    transition: visibility 0.3s linear, opacity 0.3s linear;\n}<\/pre>\n<p><strong>The JavaScript part<\/strong><\/p>\n<p>In order to let the confirmation box appear, three steps are required<\/p>\n<ul>\n<li>Scale and display the curtain<\/li>\n<li>Center the box<\/li>\n<li>Fade in the box<\/li>\n<\/ul>\n<p>To scale the curtain, first the dimensions of the visible window are evaluated<\/p>\n<p>JavaScript<\/p>\n<pre lang=\"Javascript\">function GetWindowGeometry()\n{\n    let intWidth = 0, intHeight = 0, intScrollX = 0, intScrollY = 0;\n\n    intWidth = window.innerWidth;\n    intHeight = window.innerHeight;\n\n    if ( self.pageYOffset )          \/\/ all except Internet Explorer\n    {\n        intScrollX = self.pageXOffset;\n        intScrollY = self.pageYOffset;\n    }\n    else if ( document.documentElement &amp;&amp; document.documentElement.scrollTop )          \/\/ Internet Explorer 6 Strict\n    {\n        intScrollX = document.documentElement.scrollLeft;\n        intScrollY = document.documentElement.scrollTop;\n    }\n    else if ( document.body )           \/\/ all other Internet Explorers\n    {\n        intScrollX = document.body.scrollLeft;\n        intScrollY = document.body.scrollTop;\n    };\t\n\n    return new Array( intWidth, intHeight, intScrollX, intScrollY );\n}<\/pre>\n<p>These values are then used to scale the curtain while considering a vertical scroll bar. Increasing the opacity causes the curtain to fade in based on the transition defined in CSS.<\/p>\n<p>JavaScript<\/p>\n<pre lang=\"Javascript\">function DimPage()\n{\n    const objDimmerImage = document.getElementById('busy');\n    const arrWindowGeometry = GetWindowGeometry();\n\n    \/\/ Check whether a vertical scrollbar is visible\n    if ( ( window.innerWidth - document.body.clientWidth ) &gt; 25 )\n    {\n\t\/\/ If so, subtract width of scrollbar from image width in order to \n\t\/\/ avoid a horizontal scrollbar to appear...\n\tobjDimmerImage.width = arrWindowGeometry[0] - 17;\n\t\/\/ ...and extend its height to the document height\n\tobjDimmerImage.height = document.body.clientHeight + 25;\n    }\n    else\n    {\n\t\/\/ ... else scale to inner window size\n\tobjDimmerImage.width = arrWindowGeometry[0];\n\tobjDimmerImage.height = arrWindowGeometry[1];\t\t\n    }\n\n    objDimmerImage.style.left = \"0px\";\n    objDimmerImage.style.top = \"0px\";\n    objDimmerImage.style.zIndex = \"50\";\n    objDimmerImage.style.opacity = \"0.7\";\n}<\/pre>\n<p>The corresponding function to fade out the curtain.<\/p>\n<p>JavaScript<\/p>\n<pre lang=\"Javascript\">function UndimPage()\n{\n    const objDimmerImage = document.getElementById('busy');\n    const objSpinnerImage = document.getElementById('spinner');\n\n    objDimmerImage.style.opacity = \"0\";\n\n    objSpinnerImage.style.visibility = \"hidden\";\n    objSpinnerImage.style.zIndex = \"-1\";\n\n    \/\/ Delay sending dimmer to back and resetting to original size\n    jsTimeout = setTimeout\n    (\n\tfunction()\n\t{\n\t    objDimmerImage.style.zIndex = \"-1\";\n\t    objDimmerImage.width = \"400px\";\n\t    objDimmerImage.height = \"300px\";\n\t}\n\n\t, 500\n    );\n}<\/pre>\n<p>The confirmation box is centered on the window using a generic function<\/p>\n<p>JavaScript<\/p>\n<pre lang=\"Javascript\">function PositionElementAtCenter( strElementName )\n{\n    const objElement = document.getElementById( strElementName );\n\n    \/\/ Calculate element position at center of window considering a scroll position\n    let intXPositionPx = ( window.innerWidth \/ 2 ) - ( objElement.offsetWidth \/ 2 );\n    let intYPositionPx = ( window.innerHeight \/ 2 ) - ( objElement.offsetHeight \/ 2 );\n\n    \/\/ Position element\n    objElement.style.left = intXPositionPx + \"px\";\n    objElement.style.top = intYPositionPx + \"px\";\n}<\/pre>\n<p>Putting it all together, a function can be compiled which triggers fading in the curtain and the box.<\/p>\n<p>JavaScript<\/p>\n<pre lang=\"Javascript\">function FadeInConfirmation( strMessage, strOnclickAction )\n{\n    const ConfirmationDivision = document.getElementById( \"div_confirmation\" );\n    const ConfirmationParagraph = document.getElementById( \"p_confirmation\" );\n    const ConfirmationButton = document.getElementById( \"button_confirmation\" );\n    ConfirmationParagraph.innerHTML = strMessage;\n\n    \/\/ Optional onclick action to overwrite the default one (close the box)\n    if ( strOnclickAction )\n    {\n\tConfirmationButton.setAttribute( \"onclick\", strOnclickAction );\n    }\n\n    DimPage();\n\n    PositionElementAtCenter( \"div_confirmation\" );\n\n    \/\/ Fade in\n    ConfirmationDivision.style.visibility = \"visible\";\n    ConfirmationDivision.style.opacity = \"0.95\";\n}<\/pre>\n<p>Once the button is clicked, the following function fades out the box and the curtain.<\/p>\n<p>JavaScript<\/p>\n<pre lang=\"Javascript\">function FadeOutElement( strElementName )\n{\n    var objElement = document.getElementById( strElementName );\n\n    objElement.style.opacity = \"0\";\n\n    \/\/ Delay hiding the division in order to await fading to be finished\n    jsTimeout = setTimeout\n    (\n        function()\n        {\n            objElement.style.visibility = \"hidden\";\n        }\n\n        , 300\n    );\n\n    UndimPage();\n}<\/pre>\n<p><strong>Summary<\/strong><\/p>\n<p>Compositions of various animated elements take some behavioral JavaScript code to be implemented, but if variable values are used wherever adequate, the respective maintenance effort remains low.<\/p>\n<p>You can test the result in the <a href=\"https:\/\/www.reichartonline.de\/inftec\/housekeeping\/login.php\" target=\"_blank\" rel=\"noopener noreferrer\">Housekeeping demo instance<\/a> trying to copy a unique entry like a city.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Confirmation boxes are definitely featured by any JavaScript framework. Nevertheless I was interested in learning what it took to implement configurable confirmation and decision boxes. The HTML part Just insert a hidden image to represent the box and a second one for the &#8220;curtain&#8221;. Such a curtain not only looks smart, but it avoids [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":62,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"footnotes":""},"class_list":["post-138","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/pages\/138","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/reichartonline.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=138"}],"version-history":[{"count":14,"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/pages\/138\/revisions"}],"predecessor-version":[{"id":1300,"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/pages\/138\/revisions\/1300"}],"up":[{"embeddable":true,"href":"https:\/\/reichartonline.de\/index.php?rest_route=\/wp\/v2\/pages\/62"}],"wp:attachment":[{"href":"https:\/\/reichartonline.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=138"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}