Yahoo! Modal Dialogs in Visualforce

I found this great post/tutorial (Modal Dialogs in Visualforce using the Yahoo! User Interface Library) regarding the use of the Yahoo! User Interface (YUI) Library within Visualforce pages. But what if you work for a business that uses Internet Explorer (IE) as the standard / supported browser across the enterprise? You get the security warnings dialog when accessing the Visualforce page, of course.

Security Warning in Internet Explorer Browsers

Other browsers offer warnings to users about accessing secure (https://) and non-secure (http://) items within a secure page but IE seems to be the most disruptive (in my opinion) to the User experience when working with Visualforce.

Since I never know what users will do when navigating from page to page within a Salesforce org I like to make the User experience as simple and seamless as possible. This, to me, means losing the security warnings.

So I took a little time to move all of the non-secure (http://) items for the YUI functionality to Static Resources within my Salesforce org. I knew that moving those files from remote locations on the Internet to local files within a Salesforce org would create some modifications to the way in which the YUI functionality worked within the Visualforce page. Since others may be doing this same thing, I thought it would be helpful to provide everyone with the files I used and some information regarding how to properly use them within Visualforce.

The first thing you need to know is that the files I am providing within this post are for the 2.8.2r1 version of the YUI library. Also, I am only including the YUI files needed for the modal popup that was used in the original post for the Force.com developer site.

Next, you need to know that I copied the relevant files from the http://yui.yahooapis.com domain down to my local machine for editing. The files that I copied locally are:

  • http://yui.yahooapis.com/2.8.2r1/build/yahoo-dom-event/yahoo-dom-event.js
  • Saved locally as yahoo-dom-event.js
  • http://yui.yahooapis.com/2.8.2r1/build/dragdrop/dragdrop-min.js
  • Saved locally as dragdrop-min.js
  • http://yui.yahooapis.com/2.8.2r1/build/container/container-min.js
  • Saved locally as container-min.js
  • http://yui.yahooapis.com/2.8.2r1/build/animation/animation-min.js
  • Saved locally as animation-min.js
  • http://yui.yahooapis.com/2.8.2r1/build/assets/skins/sam/skin.css
  • Saved locally as skin.css
  • All images referenced in the skin.css file.

I created a new folder labeled "image" and dropped all of the downloaded images into that folder.

All of the YUI JavaScript files for that functionality simply need to be moved to Static Resources within a Salesforce org and do not require any editing whatsoever. The only file that really requires maintenance is the skin.css file, which contains numerous non-secure image references.

For example, the skin.css stylesheet has the following class defined:

.yui-skin-sam .yui-panel .hd {
	padding: 0 10px;
	font-size: 93%;
	line-height: 2;*line-height:1.9;
	font-weight: bold;
	color: #000;
	background:url(http://yui.yahooapis.com/2.8.2r1/build/assets/skins/sam/sprite.png) repeat-x 0 -200px;
}

The issue with this class is the background property because it references the non-secure http://yui.yahooapis.com domain for the sprite.png image. So I updated that property to reference the same image file but now from my local image folder. The specific change to the class is below:

.yui-skin-sam .yui-panel .hd {
	padding: 0 10px;
	font-size: 93%;
	line-height: 2;*line-height:1.9;
	font-weight: bold;
	color: #000;
	background:url(image/sprite.png) repeat-x 0 -200px;
}

The example above is one of many image reference modifications I had to make to the skin.css stylesheet. Again, the point of these tweaks is to ensure that all image references are now local to the page where the stylesheet is used and not remote.

The fully updated stylesheet can be found here: skin.css

Now that we have all of the images, JavaScript files and updated stylesheet saved locally, we need to move those items into the Salesforce Org where we will build the Visualforce page.

You have a couple of options here. One option is to all all of these items to a zip file and then upload that single zip file as a static resource within the Salesforce org. The second option is to add only the stylesheet and image folder to a zip file and then add each individual JavaScript file and the created zip file as static resources.

I opted to go with the second option because it is easier for me to understand the various file references within my Visualforce page as I do my development. With this in mind, let’s walk through the steps for creating our Visualforce page.

Step 1 is to create a zip file, which contains the image folder with all of the YUI images and the updated skin.css file. The skin.css file should not be in the image folder when you zip up the files. Name the file style.zip. You can download the file I used from here: style.zip.

Step 2 is to upload all of the YUI files we’ve been working with. Navigate to the Static Resources area within your Salesforce org. Setup > Develop (under App Setup) > Static Resources. and click the "New" button for each. Please see the table below for the details of each uploaded file:

Name Description File Cache Control
yui_dragdrop_min_js   dragdrop-min.js Public
yui_yahoo_dom_event_js   yahoo-dom-event.js Public
yui_container_min_js   container-min.js Public
yui_animation_min_js   animation-min.js Public
yui_style   style.zip Public

Step 3 is to make the necessary code changes to the Visualforce page. The code below is originally from the Force.com Developer tutorial but I added some comments and changes at the very top indicating the exact alterations that need to be made in order to accommodate the use of Static Resource files instead of non-secure remote include files.

<apex:page standardController="Account" >
<!--
    Created by: Ron Hess & Dave Carroll
    Original Code & Tutorial: http://wiki.developerforce.com/index.php/Tutorial:_Modal_Dialogs_in_Visualforce_using_the_Yahoo!_User_Interface_Library
    
    Last Update: 1 March 2011 by Greg Hacic
    Questions?: greg@interactiveties.com

BEGIN: Modifications by Greg Hacic (greg{at}InteractiveTies{dot}com)
NOTE: remove all references to files that are in remote locations
<apex:styleSheet value="http://yui.yahooapis.com/2.6.0/build/assets/skins/sam/skin.css" />
 
<apex:includeScript value="http://yui.yahooapis.com/2.6.0/build/yahoo-dom-event/yahoo-dom-event.js" />
<apex:includeScript value="http://yui.yahooapis.com/2.6.0/build/container/container-min.js" />
<apex:includeScript value="http://yui.yahooapis.com/2.6.0/build/animation/animation-min.js" />

NOTE: add references to Salesforce Static Resource files -->

<apex:stylesheet value="{!URLFOR($Resource.yui_style,’skin.css’)}"></apex:stylesheet>
<apex:includescript value="{!$Resource.yui_yahoo_dom_event_js}"></apex:includeScript>
<apex:includescript value="{!$Resource.yui_dragdrop_min_js}"></apex:includeScript>
<apex:includescript value="{!$Resource.yui_container_min_js}"></apex:includeScript>
<apex:includeScript value="{!$Resource.yui_animation_min_js}"></apex:includeScript>
<!-- END: Modifications by Greg_Hacic (greg{at}InteractiveTies{dot}com) -->
 
<script>
    
    // Create a namespace for our custom functions
    YAHOO.namespace("force.com");

    // Function called when we want to show the dialog
    YAHOO.force.com.showMe = function() {
        document.getElementById("myPanel").style.display = "block";
        YAHOO.force.com.myDialog.show();
    }
   
    // Function called when we want to hide the dialog
    YAHOO.force.com.hideMe = function() {
        YAHOO.force.com.myDialog.hide();
    }

    // Function called when the DOM is ready to create the dialog,
    // render the dialog into the document body, add our dialog skin
    // css to the body tag, and wire up the buttons on our dialog
    YAHOO.force.com.init = function() {
        document.body.className = document.body.className + " yui-skin-sam";
        
        YAHOO.force.com.myDialog = new YAHOO.widget.Panel(
            "myPanel",  // The id of our dialog container
            { 
                    width           :   300,    // You can play with this until it’s right
                    visible         :   false,  // Should be invisible when rendered
                    draggable       :   true,   // Make the dialog draggable
                    close           :   false,  // Don’t include a close title button
                    modal           :   true,   // Make it modal
                    fixedCenter     :   true,   // Keep centered if window is scrolled
                    zindex          :   40,     // Make sure it’s on top of everything
                    
                    // This line adds the appear/vanish fade effect
                    effect          :   {
                                          effect:YAHOO.widget.ContainerEffect.FADE,
                                          duration:0.35
                                        } 
            }
         );
        
        // Render the dialog to the document.body level of the DOM
        YAHOO.force.com.myDialog.render(document.body);
    }
    
    // Add the init method to the window.load event
    YAHOO.util.Event.addListener(window, "load", YAHOO.force.com.init);
</script>

<!-- This is the page that we want to display to the user -->
<apex:outputPanel >
	<apex:pageBlock title="Basic Modal Dialog" id="none">
		<apex:pageBlockButtons >
			<input type="button" class="btn" onclick="YAHOO.force.com.showMe();" value="Popup Demo" />
		</apex:pageBlockButtons>
		<apex:outputPanel layout="block">
			<apex:outputPanel layout="block" style="margin-bottom: 10px;">
				<apex:outputLink value="http://developer.yahoo.com/yui/container/" target="_blank">
					Yahoo Developer Network - Container
				</apex:outputLink>
			</apex:outputPanel>
			<apex:outputPanel layout="block" style="margin-bottom: 10px;">
				A basic modal dialog with minimal styling and without any additional
				settings. The basic overall style is set by the CSS defined in the skins.css
				file included at the top of the page source. The example Visualforce 
				page will collect information and place it back on this page.
			</apex:outputPanel>
			<apex:outputPanel id="output" layout="block">   
				Account Name : <strong><apex:outputText value="{!account.name}" /></strong>
			</apex:outputPanel>
		</apex:outputPanel>
	</apex:pageBlock>
</apex:outputPanel>

<!-- This is the content of the modal dialog -->
<div id="myPanel" style="display: none" >
	<div class="hd">
		<apex:outputText value="Cool Modal Dialog" />
	</div> 
	<div class="bd">
		<apex:form >
			<apex:pageBlock >
				<apex:pageBlockSection columns="1">
					<apex:inputField id="fName" value="{!account.name}" />
				</apex:pageBlockSection>
			</apex:pageBlock>
			<div style="text-align: right;" >
				<apex:commandButton value="Select" oncomplete="YAHOO.force.com.hideMe();" />
				<apex:commandButton value="Cancel" immediate="true" oncomplete="YAHOO.force.com.hideMe();"/>
			</div>
		</apex:form>
	</div>
	<div class="ft" style="font-size: 10px;">
		<apex:outputPanel layout="block">
			The dialog in this demo is using a "hidden" DIV containing and contains 
			its own Visualforce Form. The information entered into the inputText 
			component is bound to data in the Apex Controller.
		</apex:outputPanel>
	</div>
</div>
</apex:page>

As you can see from the code, we only have to change a couple of lines of code to make use of those Static Resources.

Automated Exchange Rates in Salesforce.com

Reduce Repetitive Tasks, Eliminate Errors & Free Up Your Administrators.

Birthday Reminders for Salesforce.com

It might lead to a sale. Or it might make you feel good.