Tuesday, July 27, 2010

Salesforce, Internet Explorer 8 and the Missing DOCTYPE Declaration

All of my frustration with IE8 is now divided 25-75 between IE8 and Salesforce, with most of the frustration on Salesforce.

The layout scheme I described in my previous post works in all browsers except in IE8 when implemented as a Salesforce Visualforce page. Offline, I was able to reproduce the issue with the source code saved from the offending Visualforce page. Then, furthermore I was able to fix the issue by adding a simple DOCTYPE declaration at the top of the page.

The layout issues appear to be caused by the fact that Salesforce does not generate a !DOCTYPE tag at the top of the page, and IE8 just happens to assume a different !DOCTYPE than Firefox or Chrome. The !DOCTYPE that IE8 assumes must not be compatible with CSS 2.1 and HTML 4.1, the standards that I am trying to follow (although I'm probably making some mistakes along the way as well).

Regardless, Salesforce's Developerforce article "Using the Salesforce CSS in Your Apps" explicitly states (at my last viewing of the page on July 27, 2010 at 6:13 PM EDT):

Please ensure that you define the following DOCTYPE at the top of your HTML:

<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">


Ironically, if I try to add the !DOCTYPE tag before the apex:page tag, I get the following error:

Error: java.lang.NullPointerException
Error: null


Furthermore, if I try to add the !DOCTYPE tag immediately after the apex:page tag, I get a different error:

Error: A DOCTYPE is not allowed in content. at line 2


I found a Salesforce Community thread that talked about this issue, but the resolution is ambiguous to me and does not clearly show how to get the infinitely important !DOCTYPE tag into the page. The thread "Changing doctype of a Visualforce Page" shows many people having success with getting the !DOCTYPE tag to stick, but for some reason it is still not working for me.

I'm going to log a case with Premier Support and poke around some more to see if I can't get this to work in the next 15 minutes before the lights shut off here in the office.

Sunday, July 25, 2010

Better Understanding of Using CSS for Page Layouts

After hours and hours of exhaustion and frustration, I've finally arrived at what I can accept as a decent implementation of a webpage with a gradient border.



The page header and page footer will stay in-position with the page, and the footer will always appear at the bottom of the screen no matter how it is resized or how much content is on the page.

The final implementation has code that looks like the following in the HTML:

<!-- Create the backdrop. -->

<div class="Backdrop">
<div class="BackdropLeft">
</div>
<div class="BackdropRight">
</div>
</div>

<!-- Create the page (containing content). -->

<div class="Page">
<div class="PageHeader">
PageHeader
</div>
<div class="PageBody">
PageBody
</div>
<div class="PageFooter">
PageFooter
</div>
</div>

Then, CSS in the background was used to do the trick to position everything correctly.

body {
background-color:#987431;
} /* body */
body>div {
width:800px;
} /* body>div */
div.Backdrop {
position:fixed;

left:0;
margin-left:auto;
margin-right:auto;
right:0;

top:0;
margin-top:0;
height:100%;
margin-bottom:0;

background-color:white;
} /* div.Backdrop */
div.Backdrop>div {
position:fixed;

width:100%;

height:100%;
} /* div.Backdrop>div */
div.BackdropLeft {
background-position:0;
background-image:url("gradient-rl-nu_black-nu_gold.jpg");
background-repeat:repeat-y;
} /* div.BackdropLeft */
div.BackdropRight {
background-position:760px;
background-image:url("gradient-lr-nu_black-nu_gold.jpg");
background-repeat:repeat-y;
} /* div.BackdropRight */
div.Page {
position:absolute;

left:0;
margin-left:auto;
margin-right:auto;
right:0;

top:0;
margin-top:0;
margin-bottom:0;

min-height:100%;
} /* div.Page */
div.Page>div {
left:0;
margin-left:auto;
width:720px;
margin-right:auto;
right:0;
} /* div.Page>div */
div.PageHeader {
position:absolute;

top:0;
margin-top:0;
height:100px;

background-color:red;
} /* div.PageHeader */
div.PageBody {
background-color:white;

padding-top:100px;
padding-bottom:100px;
} /* div.PageBody */
div.PageFooter {
position:absolute;

height:100px;
margin-bottom:0;
bottom:0px;

background-color:blue;
} /* div.PageFooter */

I feel like I have a much better idea of how to layout webpages now. Just learning all of the available tools (properties) is a huge challenge, which included almost 100 pages of reading on the W3C website for the CSS 2.1 specification. Whew!

Wednesday, July 21, 2010

apex:actionSupport Does Not Work in Form with Required apex:input Components

After spending over two hours troubleshooting what seemed like a ridiculous problem, I discovered that the apex:actionSupport component does not work if any other apex:input* components have the required attribute set to true.

Unbelievable, the kind of stuff that's missing from the Visualforce documentation...

Monday, July 19, 2010

Tips on Getting Started with Ajax in Salesforce

It appears that there are a few things to keep in mind in order to reduce frustration and wasted time when implementing AJAX behavior with Salesforce.

  • The reRender attribute only works with apex:output* standard components.

  • The apex:outputPanel standard component produces a DIV tag, which means that it cannot be used to encapsulate table rows or table cells. However, the component can be used within a table cell.



I don't know why, but it took me a few hours to figure this out while I was trying to achieve Ajax behavior with as few Apex components as possible.

Tuesday, July 13, 2010

How to Exclude Address Lists from Outlook Autocomplete

Problem:

I received a rather unhappy email from a student today regarding an email on which that student was incorrectly copied. It turns out that this student's name is the same as the contact in my Outlook address book that I was trying to reach.

Further testing revealed that when I composed a new email, my Outlook address book was never even consulted for autocomplete, since Outlook would automatically select the student's address without my confirmation. Pressing Ctrl+Enter like I usually do to quickly send out emails would cause the student's email address to be automatically selected with no indication to me that the selection was actually incorrect.

So... what to do to prevent myself from getting into trouble later...

Solution:

Fortunately, I came across a Microsoft article that gave me a hint after I searched for "microsoft create a filtered global address list" on Google.

"HOW TO: Create a New Global Address List with a Custom Search by Using an LDAP Filter"
Microsoft Support
http://support.microsoft.com/kb/823151

The article gave me hope, and I looked more into my address book settings where I found the answer.

So, without further ado, the steps to reconfigure the autocomplete settings are:

  1. Open the Address Book.

  2. Click Tools > Options.

  3. Add, remove and reorder the lists used by the check names and autocomplete features.