We currently use the lead detailed page to display lead information. We have a requirement where we need to create a custom button on the lead detailed page on the standard layout where on clicking the button, we need to display additional attributes of the lead on a popup panel on the same detail page. We currently do this on a visual force page which opens a new window every time. What we want to display is a modal window on the standard page layout or a popup panel where we can embed a visual force page and display some more attributes and on clicking a button, the popup disappears the detail page is rendered. Do any of you guys have examples of doing this or sample code might help?
Buyan
Best Answer
This is a problem I had to solve recently for extensive use within an org, so towards that end I made a more generic framework that could be plugged into any org. So I'm going to try and stick to the how of using this approach, and why I've made some of my choices within this approach, without going to heavily into why you should use this over alternatives. Caveat emptor as always :)
Check out this Gist for some boilerplate, first up (plus a few instructions in the files): https://gist.github.com/Oblongmana/6771197
Note that this solution is:
The basic problem
Getting Modals to play nice is kind of unpleasant, primarily because there are many many places where css and js can clash with Salesforce. Additionally, you generally want to be up and running quickly wihtout having to do to much js, css, and messy html/vf markup.
As such, my view is that you need a framework that decouples itself from any thing "Salesforcey", is stable, and actively minimises the amount of javascript and functional css you have to write, so you can focus on data presentation instead
So towards that end, we use jQueryUI as a base - as this includes the "dialog" group of functionality - which provides you with the ability to do modals.
Get rolling with jQueryUI
As mentioned above, we want to try and be de-coupled from anything "Salesforcey", to minimise the chance of future releases breaking functionality.
As such, when we download jQueryUI, we're going to use a custom CSS scope (an option they provide you). When you define the modal area on your page later, this scope is going to ensure that the heavyweight jQueryUI css only gets applied to your modal when it's being popped, and not to anything in the main part of your page - minimising the chance of ugly css clashes.
Get jQuery
Make sure you've got jQuery downloaded (http://jquery.com/download/) and added as a Static Resource called jQuery.
Alternatively, you could use a CDN. I personally don't - in the unlikely event the CDN has a problem while Salesforce stays up, you'll wind up with confused clients.
Set up your Visualforce page
See the Gist mentioned above for a complete example of a page - I'm just going to put relevant snippets in here.
So as mentioned above, you want to have your modal de-coupled from anything too "Salesforcey" so it won't break. As such, you are going to set up your modal in a way that avoids integrating with the rest of the page. In the below example, you'll see there's a form, containing your regular page content as usual, but then below outside of the form, there's a modal div which has two important characteristics:
Important things in terms of set up here:
The launch/close buttons also have class "btn" - one of the only instances we use something "Salesforcey" (this gives the buttons a Salesforce button appearance)
Now you mentioned that you want to put a visualforce page in the modal? Easy peasy.
Suppose I have a page called TempPage. It looks like this:
I can just change the modal's contents like so - adding the
<apex:composition>
tag to pull that page in:This displays exactly as you would expect it to,
pageBlock
and all. See right at the end for a picture example.Add custom javascript to the modal's initialise, open, and close functions
So here's where it gets a bit fun, and you're going to be using some boilerplate I've already written. You can roll this yourself if you'd prefer, but I'm going to give you a quick run-down on my rationale. This file is located in the Gist mentioned above, called common-modal.js.
NOTE: that you may want to just add the file as a Static Resource and use it without reading the below, as it's not the simplest of javascript, and understanding this section fully IS NOT NECESSARY TO BEING ABLE TO USE IT IN YOUR PAGE! If this sounds like you, just add common-modal.js as a static resource called "modal", then skip down to the "Initialise your modal on the page" section.
The first function in the file is
initialiseDialogs(jQueryDialogSelectorsArray)
. This function takes in an array of jQuery selectors. Each element in the array should a selector which grabs adiv
holding all of your modal's content.This calls the jQueryUI dialog function on the modal div, with params indicating it should be a modal, width, height, etc. It also adds functions which jQueryUI will call on
open
andbeforeClose
which wrap and unwrap the modal in a div with class "jqueryuidialog" (which ensures the jQueryUI css only gets applied to the modal - this is why we did that work earlier getting the custom css scope when we downloaded jQueryUI).The next function in the file is
initialiseDialogOpeners(jQueryDialogSelectorsArray,jQueryOpenerSelectorsArray)
. This function takes in the array of jQuery selectors which select the modal divs, and an array of jQuery selectors which selects the elements that you should click to open the modals (e.g.jQueryOpenerSelectorsArray[0].click()
should openjQueryDialogSelectorsArray[1]
). This gobbles the usual input event by callingpreventDefault()
so you don't get any unexpected form submissions!The next function in the file is
initialiseDialogClosers(jQueryDialogSelectorsArray,jQueryOpenerClosersArray)
. This is effectively identical toinitialiseDialogOpeners
above, but calls.dialog("close")
instead. I won't clutter this further by elaborating :)Initialise your modal on the page
First, you need to import the Static Resources we've been fluffing around with in previous steps. Depending on how closely you followed the steps, you may need to tweak these imports slightly.
Finally (phew!), we add some code which sets up our modal and binds our open and close events. Basically, on document ready, we set up 3 arrays - one listing the modals, and then 2 others listing the opener and closer elements respectively. We then call the common-modal.js functions (described above/imported as a Static Resource)
Everything should now work :D