Skip to main content

Ever want to detect when the ‘X’ or Escape Key is clicked/pressed to initiate a dialog close - or better yet, disable it completely? Ever want to hook open/close events or run some logic that would stop a dialog from closing in certain situations?


I’ve had this need on many occasions and decided it was time to polish up the custom component I had written. There are many posts in the community regarding this topic so I thought I would share.


Enter, the Popup Controller custom component.


The component hooks the jQuery dialog and its events and invokes snippets that you define when various events occur. It also contains a feature for “hiding the ‘X’” and “disabling the escape key from closing the dialog.” Each popup will have its own Popup Controller so you can vary functionality from popup to popup.


Please note:


  1. This has not been tested yet in every possible situation (e.g. popups in popups). That said, it should work in all cases and if you do find a problem, please let me know.

  2. This is written for Skuid 7.x (Banzai) but very minor modifications (builders.js) would be needed to support Skuid 6.x.

To use it:


  1. Create a new Component pack with a prefix of “myns” and Component Pack Label of “My Namespace Components”

  2. Upload the zip file from here to replace the default Static Resource created by Skuid for the pack

  3. Place the Popup Controller Component as the first component on any popup

  4. Set the Popup Controller component properties as appropriate for your situation

You of course can modify the component pack to fit your specific namespace/module name, etc.


Below is a sample XML page that demonstrates the functionality. To use the sample page, complete steps #1, #2 & #3 from above, then create a new skuid page and copy/paste the XML below.


Feedback, issues, etc. appreciated. Enjoy!


Sample Page XML (uses Account object, standard fields, etc.)


<skuidpage unsavedchangeswarning="yes" personalizationmode="server" showsidebar="true" showheader="true" tabtooverride="Account">   <models>
<model id="Account" limit="100" query="true" createrowifnonefound="false" sobject="Account" adapter="" type="">
<fields>
<field id="Name"/>
<field id="CreatedDate"/>
</fields>
<conditions>
<condition type="param" value="id" field="Id" operator="=" enclosevalueinquotes="true" novaluebehavior="noquery"/>
</conditions>
<actions/>
</model>
</models>
<components>
<pagetitle model="Account" uniqueid="sk-3ro7Me-67">
<maintitle>
<template>{{Model&#46;labelPlural}}</template>
</maintitle>
<subtitle>
<template>Home</template>
</subtitle>
<actions>
<action type="multi" label="Edit in Popup With X" icon="sk-icon-edit">
<actions>
<action type="showPopup">
<popup title="New Popup" width="90%">
<components>
<myns__mynspopupcontroller uniqueid="sk-3roGN_-93" oncreate="onCreateSnippet" onopen="onOpenSnippet" onbeforeclose="onBeforeCloseSnippet" onclose="onCloseSnippet" hideclose="false" disableescape="false"/>
<basicfieldeditor showheader="true" showsavecancel="false" showerrorsinline="true" model="Account" buttonposition="" uniqueid="sk-3royd7-385" mode="read">
<columns>
<column width="100%">
<sections>
<section title="Section A" collapsible="no">
<fields>
<field id="Name"/>
</fields>
</section>
</sections>
</column>
</columns>
</basicfieldeditor>
<pagetitle uniqueid="sk-3rp3OG-403" model="Account">
<actions>
<action type="multi" label="Save" icon="sk-icon-save">
<actions>
<action type="save"/>
</actions>
</action>
<action type="multi" label="Cancel" icon="sk-icon-cancel">
<actions>
<action type="closeTopmostPopup"/>
</actions>
</action>
</actions>
<conditions>
<condition type="contextrow" field="Id" mergefield="Id" operator="="/>
</conditions>
</pagetitle>
</components>
</popup>
</action>
</actions>
</action>
<action type="multi" label="Edit in Popup Without X" icon="sk-icon-edit">
<actions>
<action type="showPopup">
<popup title="New Popup" width="90%">
<components>
<myns__mynspopupcontroller uniqueid="sk-3roGN_-93" oncreate="onCreateSnippet" onopen="onOpenSnippet" onbeforeclose="onBeforeCloseSnippet" onclose="onCloseSnippet" hideclose="true" disableescape="true"/>
<basicfieldeditor showheader="true" showsavecancel="false" showerrorsinline="true" model="Account" buttonposition="" uniqueid="sk-3royd7-385" mode="read">
<columns>
<column width="100%">
<sections>
<section title="Section A" collapsible="no">
<fields>
<field id="Name"/>
</fields>
</section>
</sections>
</column>
</columns>
</basicfieldeditor>
<pagetitle uniqueid="sk-3rp3OG-403" model="Account">
<actions>
<action type="multi" label="Save" icon="sk-icon-save">
<actions>
<action type="save"/>
</actions>
</action>
<action type="multi" label="Cancel" icon="sk-icon-cancel">
<actions>
<action type="closeTopmostPopup"/>
</actions>
</action>
</actions>
<conditions>
<condition type="contextrow" field="Id" mergefield="Id" operator="="/>
</conditions>
</pagetitle>
</components>
</popup>
</action>
</actions>
</action>
</actions>
</pagetitle>
<basicfieldeditor showheader="true" showsavecancel="false" showerrorsinline="true" model="Account" buttonposition="" uniqueid="sk-3uLhmh-94" mode="read">
<columns>
<column width="100%">
<sections>
<section title="Section A" collapsible="no">
<fields>
<field id="Name"/>
<field id="CreatedDate"/>
</fields>
</section>
</sections>
</column>
</columns>
</basicfieldeditor>
</components>
<resources>
<labels/>
<css/>
<javascript>
<jsitem location="inline" name="popupSnippets" cachelocation="false" url="">(function(skuid){
var $ = skuid&#46;$;
skuid&#46;snippet&#46;registerSnippet('onCreateSnippet', function(eventArg) {
window&#46;alert('onCreateSnippet');
});
skuid&#46;snippet&#46;registerSnippet('onOpenSnippet', function(eventArg) {
window&#46;alert('onOpenSnippet');
});
skuid&#46;snippet&#46;registerSnippet('onBeforeCloseSnippet', function(eventArg) {
window&#46;alert('onBeforeCloseSnippet - wasXButton=' + eventArg&#46;wasXButton + ' / wasEscapeKey=' + eventArg&#46;wasEscapeKey);
var prohibitClose = eventArg&#46;wasXButton || eventArg&#46;wasEscapeKey;
&#47;&#47; returning false will prohibit close
return !prohibitClose;
});
skuid&#46;snippet&#46;registerSnippet('onCloseSnippet', function(eventArg) {
window&#46;alert('onCloseSnippet');
});
})(skuid);</jsitem>
</javascript>
</resources>
<styles>
<styleitem type="background" bgtype="none"/>
</styles>
</skuidpage>

This thing is awesome!!! Why isn’t this just the way popups work!

Barry, you are the man!

I mean, I’ve done some of what you’ve done, but this has way more polish on it for sure. This is a way complete solution for the popup. All the bells and whistles included!

Still can’t believe I missed this.


Glad you like it Pat.  Its worked out very well for me, enjoy!


Thanks Barry.  Really appreciate your sharing here. 


This idea is listed as implemented. Does this mean this will be in the next release?

Also, when is the next release going to be?


Or was the idea marked implemented because Barry implemented it?  I am also lost here.


If I were to guess, I think it was marked as implemented based on my posting.  I agree that the workaround provided in this post is implemented but the features that this workaround is attempting to solve for (or at least make it easier) haven’t been implemented.  There are various posts through the community requesting features to be added to popups (disable ‘X’,’ disable escape, control vertical positioning, run snippets before/after, etc).  The custom component here provides hooks for all of that, just not in a stock feature.

Just making an educated guess here but I don’t think this post being marked as implemented is an indication that the features it provides are planned for the next release (although I could be wrong).

Anna - Can you confirm?  Possibly each of the various individual posts in the community asking for these individual features are being tracked internally separately?  Or should we create a new post asking for the features so that they might be added at some point?


Not sure why this is posted in “implemented”, but “After Close Actions” are in Update 7, we’re in the final testing phases of that release right now.


Awesome!!!

ETA on update 7?


Don’t quote me, but early next week.


Awesome news Ben, having “After Close” could solve for several of the use cases.

Will it provide a mechanism to detect if the dialog was closed via ‘X’ or ‘Escape’ vs some other means?



The actions will be triggered however the popup is closed, but will not differentiate on the method of closing.


Thanks for the update Ben.  

Are there plans to add ability to disable ‘x’/escape, have different events sequences for ‘cancel’ and ‘not cancel’, etc.?


We haven’t considered doing that, but it makes sense for options to remove the ‘x’/escape.

I’m not quite sure what you mean by ‘cancel’ and ‘not cancel’. I don’t think this made it into update 7, but we are thinking of adding a “run on close actions” checkbox to “close popup” actions, so you could decide whether to skip or run “on close actions”.


I can’t speak for all, but in my use cases and others I’ve seen in the community, there’s a need to run a different set of actions depending on if the user is “cancelling” the dialog or “saving/continuing/etc.” (aka. “not cancelling” - I used this is a generic way of expressing anything that isn’t a cancel, sorry for the confusion).

If ‘X’ and escape were able to be disabled, then the only way a dialog could be ‘closed’ is via a page title button on the dialog (or javascript) which allows the page designer to put action sequences on those buttons and not have to worry that they won’t fire (e.g. as a result of pressing ‘X’ or escape since they wouldn’t be there).

If ‘X’ and ‘Escape’ are still available to the end user, then the page developer needs to be able to differentiate between cancel/save operations with an “close” event because they would likely trigger different action sequences.

For example, if the user presses ‘cancel’/‘x’/‘escape’, the action sequence might cancel models changes while if they press ‘save’/‘continue’ the action sequence might save model changes.  Without a way to differentiate (or ensure that the only way to close a dialog is via a custom button) there is no way to handle the different paths.  Even with “After Close” or “Run on Close”, you wouldn’t be able to do different things in different situations unfortunately.

Hope I’m making sense 🙂




Yeah, this all makes sense. Hopefully we’ll be able to get portions of this into the product in upcoming releases.


Sounds great, thanks Ben!


Hi @Berry, for using this component does all these parameters (oncreate, onopen, onbeforeclose, onclose) are mandatory?


<myns__mynspopupcontroller uniqueid="sk-3roGN_-93" oncreate="onCreateSnippet" onopen="onOpenSnippet" onbeforeclose="onBeforeCloseSnippet" onclose="onCloseSnippet" hideclose="true" disableescape="true"/>

I just want to hide the X symbol on the pop-up and remove escape button actions. So I just put like below and it is not working for me. Let me know if any more changes that I need to put to make it work.


<myns__mynspopupcontroller uniqueid="sk-3roGN_-93" hideclose="true" disableescape="true"/> 

Thanks.


Hello Dinesh -

The oncreate/onopen/etc. should all be optional.  When you say it’s not working for you, can you provide specifics as to what’s not working, any error messages in the browser developer console, etc.

If you can create a full sample page using only stock objects, I’m happy to take a look.

Thanks!