Tuesday, November 29, 2011

Change CSS on the fly in GWT

It is common in large, enterprise applications to have customers that resell your application. These customers want your application to appear as their own. In a web application, this is typically provided through dynamically assigning a CSS stylesheet to each customer. This can easily be done in GWT as simply as in more traditional web applications.

Our Sample Application:
For our sample application, let's create something simple. We will use a DeckPanel to switch between a widget that allows the user to choose a specific customer branding (Figure 1) and one that displays the chosen branding (Figure 2).
Figure 1
Figure 2


Creating your Project:
Create your project normally or you can download the sample project. Continue to use your module's CSS for all common, non-branded styling. We will handle customer-specific branding & styling later. For the sake of simplicity, let's ignore good programming practice and place all of our logic in the entry module.
public class Demo implements EntryPoint, ClickHandler { 
    private DeckPanel root; 
    private String cssId; 
 
    public void onModuleLoad() { 
        try { 
            root = new DeckPanel(); 
            root.add(createChoices()); 
            root.add(createWholesalePanel()); 
            root.showWidget(0); 
            RootPanel.get().add(root); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
    } 
 
    public Widget createChoices() { 
        HorizontalPanel panel = new HorizontalPanel(); 
        panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); 
        Button button = new Button("Show Customer #1"); 
        button.addClickHandler(this); 
        panel.add(button); 
        button = new Button("Show Customer #2"); 
        button.addClickHandler(this); 
        panel.add(button); 
        return panel; 
    } 
 
    public Widget createWholesalePanel() { 
        VerticalPanel panel = new VerticalPanel(); 
        panel.setWidth("100%"); 
        panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); 
        panel.addStyleName("boxBg"); 
        Label label = new Label("Customer Branded Contents"); 
        label.addStyleName("boxFg"); 
        panel.add(label); 
        Button button = new Button("Show Choices"); 
        button.addClickHandler(this); 
        panel.add(button); 
        return panel; 
    } 
 
    public void onClick(ClickEvent event) { 
        Button button = (Button) event.getSource(); 
        String buttonText = button.getText(); 
        if ("Show Choices".equals(buttonText)) { 
            showChoices(); 
        } else { 
            applyBranding(buttonText.substring(buttonText.length() - 1)); 
        } 
    } 
 
    protected void showChoices() { 
        root.showWidget(0); 
    } 
 
    protected void applyBranding(String aCustNo) { 
        // do nothing for now 
    }  
}      

Handle Customer Styling:
Even though we are going to brand our application, there is still a lot of shared styling. You will want to use your module's CSS for this styling. Create a "Cust1.css" and a "Cust2.css" file and place them in your web app directory. We will switch between these based on which customer is chosen.
Cust1.css .boxBg {
background: black;
}
.boxFg {
color: white;
}
Cust2.css .boxBg {backgroundwhite;}.boxFg {colorblack;} 
Using GWT, we can add a DOM element that points to the correct CSS file on the fly. Our logic will add the element if it's missing or point it to the appropriate CSS file based on the customer selection.
    protected void applyBranding(String aCustNo) { 
        root.showWidget(1); 
        LinkElement styleEl = (LinkElement) Document.get().getElementById(cssId).cast(); 
        boolean needsInsert = false; 
        if (styleEl == null) { 
            styleEl = Document.get().createLinkElement(); 
            styleEl.setRel("stylesheet"); 
            styleEl.setType("text/css"); 
            styleEl.setId(cssId); 
            needsInsert = true; 
        } 
        styleEl.setHref("Cust" + aCustNo + ".css"); 
        if (needsInsert) { 
            Document.get().getElementsByTagName("head").getItem(0).appendChild(styleEl); 
        } 
    }
 Now clicking the different buttons will give you two different styles for the same screen with no further changes to your code.
Customer #1
Customer #2

You can also specify the CSS in your HTML. The key is to specify the "id" attribute so it can be found and replaced as needed. This also allows you to specify a default "branding" CSS to use.

No comments:

Post a Comment