Jump to content


  • Posts

  • Joined

  • Last visited

melsenc's Achievements

  1. I came up with a solution for bulk edit pop-ups, which may address your detail screen problem (basically I add a .click() handler to the link that would open the pop-up - for you it would probably be the link to see details - then use jquery to pick up the pop-up and place it within the modal body after it is written to the page). The link is here: But I'm having trouble with a datapage within a modal that uses autocomplete and calendar pop-up fields. I think targeting the autocomplete suggestions to make them visible would be a different process from what I came up with for bulk edit. Have you had any further progress with your investigations?
  2. Hi all, I wanted to share a solution I came up with, which might be helpful for you. Problem: I have recently been trying to streamline page loading times, and one of the ways I've done this is to move record update datapages to Bootstrap 5 modals. It was working great for me with single record update datapages embedded in modals, but when it came to a report datapage, with a bulk edit feature, I was stumped. See the attached image. Basically, when I clicked the edit button, the pop-up for bulk edit would show up, but it would be BEHIND the modal (see my attached screenshot). Since I have my modal set to static background, that basically meant I wasn't able to edit anything in the pop-up window until I closed the modal. Not helpful! Solution: Use jQuery to assign a .click() handler to any bulk edit buttons in my datapage that is embedded in the modal. The .click() handler will wait half a second (to give the bulk edit pop-up time to be written to the page), then it will move the bulk edit pop-up div to inside the modal body. This solution is only for situations where you're including jQuery and Bootstrap 5. Here's my html modal, which lives at the bottom of my html page where the first datapage is embedded: <div class="modal fade" id="cb-modal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="imgModalLabel" aria-hidden="true"> <div id="cb-modal-dialog" class="modal-dialog modal-larger-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="cb-modal-title">Modal title</h5> <button type="button" class="btn-close bg-transparent" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <div id="cb-modal-body" class="cb-form-fluid cb-form-resp"></div> </div> </div> </div> </div> The datapage that is embedded in that html page happens to be a report style datapage. Every record includes a link which will dynamically embed a second datapage in my modal, and open it. Complete with params. Here is the code for one of my links: <a href="#" role="button" data-bs-toggle="modal" data-bs-target="#cb-modal" onclick="openModal( 'Edit/Add Items', '1dae6000bcb0b9a06b9841e2a9c0', '?cbResetParam=1&garments_CustomerInvoiceNo=[@field:PSST_CustomerInvoiceNo]&garments_TrackingNo=[@field:PSST_TrackingNo]&garments_Order_id=[@field:PSST_workOrder_id]&garments_CustCode=[@field:Garments_Items_CustCode]&garments_ShipVia=[@field:Garments_Items_ShipVia_endcodedForURL]&garments_ShipDate=[@field:PSST_ShipDate]&garments_Distributor=[@field:Garments_Items_Distributor_encodedForURL]&garments_Whse=[@field:PSST_Whse]&garments_CustomerName=[@field:Garments_Items_CustomerName_encodedForURL]&garments_CustomerPO=[@field:Garments_Items_CustomerPO_encodedForURL]&garments_CustomerAccount=[@field:Garments_Items_CustomerAccount]' );">Edit/Add Items</a> Here is my function for openModal(), saved in an external javascript file, which is included with my html page: // function - deploy DP in modal function openModal(modalTitle, appKey, params) { $('#cb-modal-body').html(''); deployDP('cb-modal-body', appKey, params); $('#cb-modal-title').html(modalTitle); // draggable modal $(".modal-header").on("mousedown", function(mousedownEvt) { var $draggable = $(this); var x = mousedownEvt.pageX - $draggable.offset().left, y = mousedownEvt.pageY - $draggable.offset().top; $("body").on("mousemove.draggable", function(mousemoveEvt) { $draggable.closest(".modal-content").offset({ "left": mousemoveEvt.pageX - x, "top": mousemoveEvt.pageY - y }); }); $("body").one("mouseup", function() { $("body").off("mousemove.draggable"); }); $draggable.closest(".modal").one("bs.modal.hide", function() { $("body").off("mousemove.draggable"); }); }); } function deployDP(containerID, appKey, params) { var params = params || ''; var dataPageScript = document.createElement("script"); var container = document.getElementById(containerID); dataPageScript.src = cbDataPagePrefix + appKey + '/emb' + params; container.innerHTML = ''; container.appendChild(dataPageScript); } Finally, in the Footer in the Configure Results Page Fields section of my second datapage - the one that is embedded dynamically within the modal - I have this code: <script type="text/javascript"> document.addEventListener('DataPageReady', function (event) { $('#cb-modal .cbResultSetBulkEditActionLink').click(function () { setTimeout(function () { // gives the bulk edit update form time to load if (document.getElementById('BulkUpdateForm') && document.getElementById('cb-modal')) { $('#cb-modal div.modal-body').append($('#BulkUpdateForm')); // moves the bulk edit update form inside the modal body, thereby making it editable while the modal is open. } }, 500); }); $('#cb-modal .cbResultSetBulkDeleteActionLink').click(function () { setTimeout(function () { // gives the delete confirmation time to load if (document.getElementById('Alert') && document.getElementById('cb-modal')) { $('#cb-modal div.modal-body').append($('#Alert')); // moves the delete confirmation alert inside the modal body. } }, 500); }); }); </script> I know this is a really specific example, but it seemed to me like something that could come up for other people, so I figured I'd share! Hope this is helpful.
  3. Lastly, I wanted to share my solution for adding back in the spinner, now that I'm handling the Javascript validation on my own. At the bottom of the body of my HTML page, I have this spinner div: <div id="loading-mask" class="container-fluid" style="display: none;"> <div class="row" style="height:100%;"> <div class="col d-flex align-items-center justify-content-center"> <img src="files/spinner.svg" alt="spinner loading icon" class="img-fluid my-auto"> </div> </div> </div> and this script element: <!-- Validate the New Job form with javascript, to allow the spinner to function correctly --> <script> // (The Caspio required markers will be added from the Job New datapage footer) // Throw an alert and cancel form submission if required fields are left blank document.addEventListener("BeforeFormSubmit", function tx(Ev) { var field1 = document.getElementsByName("InsertRecordjobType")[0].value; var field2 = document.getElementsByName("InsertRecordmachine_group")[0].value; var field3 = document.getElementsByName("InsertRecordquantity")[0].value; var arr = []; // Don't require quantity if job department is ART. Only make machine_group required if the job department isn't ART, DTG, or O. if ( field1.startsWith('A') ) { arr = [field1]; } else if ( field1.startsWith('D') || field1.startsWith('O') ) { arr = [field1, field3]; } else { arr = [field1, field2, field3]; } if (arr.includes("")) { Ev.preventDefault(); //from the function tx(Ev) above, prevents Form to Submit alert("Please fill all required fields."); } else { navButtonSpinner(); } }); </script> The key part of the script element is the function call of navButtonSpinner(), which I define in an external .js file thus: function toggleDisplayBlock(id) { var x = document.getElementById(id); x.style.display = "block"; } function navButtonSpinner() { toggleDisplayBlock("loading-mask"); } Thanks for your help, @TellMeWhy!
  4. Thank you. I was able to add this at the bottom of my html page. I wanted to add that I also wrote some script for the footer of my datapage, to dynamically add the styling of Caspio's required asterisk, to add a visual clue for which fields are required: <script> document.addEventListener('DataPageReady', function (event) { // Add the required form field styling, to work with the javascript validation in the parent html page var label1 = $("label[for*='InsertRecordjobType']"); var label2 = $("label[for*='InsertRecordmachine_group']"); var label3 = $("label[for*='InsertRecordquantity']"); var jobDept = document.getElementsByName("InsertRecordjobType")[0].value; var labels = [label1, label2, label3]; // Required fields will be hidden by the datapage Rules if they aren't required. // (Don't require quantity if job department is ART. Only make machine_group required if the job department isn't ART, DTG, or O.) // Add the required asterisk for required fields $.each(labels, function (i, label) { var originalHTML = $(label).html(); originalHTML += '<span class="cbFormRequiredMarker"><span class="cbFormRequiredMarker">*</span></span>'; $(label).html(originalHTML); }); });
  5. I'm willing to investigate javascript validation if it is the only way to display a loader WHILE my form is in the process of submitting. The reason I want to do this is: my form takes a long time to submit, and I want to display a visual representation of the form submitting to my users, so they know something is happening. I have already been able to cut down the submission time from roughly 12 seconds to around 5 seconds, by changing the data source for the datapage to just one table, rather than a complicated joined View. However, getting it to be less than 5 seconds is still going to be a big project for me. Do you have any advice for writing javascript for form validation? The main thing I need to validate is I want to make sure required fields have been filled out. Thanks!
  6. I'm curious if anyone has been able to take this logic a bit further and only display the loading screen content IF there are no errors in the form. I have tried a variation of this, but I want the user to be able to correct form errors before showing the loading screen content. I want my loading screen content to prevent any further clicking on the page, so I set it with a high z-index, and sized it to fill the window. I went down a long rabbit hole and found this Codepen pen: https://codepen.io/sakamies/pen/yzYypW I forked it here, and customized the code a little to match what I want to accomplish: https://codepen.io/melsenc/pen/eYWwjXX I tried incorporating this code into my Caspio datapages, embedded in my html-based website with jQuery and Bootstrap 5 included. It seems this code is not catching the form correctly. I'm not sure if this is relevant, but most of my html pages have multiple form datapages on them. I target the correct form by querying document.forms[0] or document.forms[1], etc. This is the code I would include in a script on my html page: var loadingSpinnerHTML = '<div id="loading-mask" class="container-fluid"><div class="row" style="height:100%;"><div id="spinner" class="col d-flex align-items-center justify-content-center"><img href="files/spinner.svg" class="img-fluid my-auto" /></div></div></div>'; var editJobForm = document.forms[0]; var newSpinner = new LoadingSpinner(editJobForm); I have tried testing this functionality just in the Chrome browser developer console after the page has fully loaded, and it doesn't seem to have an effect, because even though the form I submit takes a few seconds to submit, my loading spinner does not become visible at all before the browser moves to the destination page. Is there javascript functionality going on behind the scenes for my datapage that is preventing me from interfering with the form submission events? I'd love to know if anyone has had any luck figuring this out.
  • Create New...