上几篇开发的Button和TextBox组件,一直采用的是claro皮肤,代码是固定写死的: @ResourceDependency(library = "dijit/themes/claro", name = "claro.css", target = "head") }) body class="claro" 因为所有的组件都存在
上几篇开发的Button和TextBox组件,一直采用的是claro皮肤,代码是固定写死的:
@ResourceDependency(library = "dijit/themes/claro", name = "claro.css", target = "head") })
<body class="claro">
因为所有的组件都存在换肤需要,所以在继续开发更多组件以前,我先解决换肤问题。上一篇实现了自定义<h:head>以后,换肤就好办了,只需要<head>中加入换皮肤所需的css,并在页面加载时设置body的class,就可以实现换肤了。
修改HeadRenderer.java
package org.dojo4j.component; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.faces.component.UIComponent; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.render.FacesRenderer; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @FacesRenderer(componentFamily = Head.COMPONENT_FAMILY, rendererType = Head.COMPONENT_TYPE) //直接继承com.sun.faces.renderkit.html_basic.HeadRenderer,修改部分渲染代码 public class HeadRenderer extends com.sun.faces.renderkit.html_basic.HeadRenderer { public static final String THEME_KEY = "dojo4j.theme"; public static final String DEFAULT_THEME = "claro"; private String theme = null; @Override public void encodeEnd(FacesContext context, UIComponent component) throws IOException { HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest(); ResponseWriter writer = context.getResponseWriter(); //加入dojo.css引用,因为每个dojo组件都需要dojo.css支持,所以加到head里避免重复生成 writer.startElement("link", component); writer.writeAttribute("type", "text/css", null); writer.writeAttribute("rel", "stylesheet", null); writer.writeAttribute("href", request.getContextPath() + context.getExternalContext().getRequestServletPath() + "/javax.faces.resource/dojo/resources/dojo.css", null); writer.endElement("link"); //加入皮肤.css引用 this.theme = getTheme(context); writer.endElement("link"); writer.startElement("link", component); writer.writeAttribute("rel", "stylesheet", null); writer.writeAttribute("href", request.getContextPath() + context.getExternalContext().getRequestServletPath() + "/javax.faces.resource/dijit/themes/" + this.theme + "/" + this.theme + ".css", null); writer.endElement("link"); //加入dojo.js引用,因为每个dojo组件都需要dojo.js支持,所以加到head里避免重复生成 writer.startElement("script", component); writer.writeAttribute("type", "text/javascript", null); writer.writeAttribute("src", request.getContextPath() + context.getExternalContext().getRequestServletPath() + "/javax.faces.resource/dojo/dojo.js", null); writer.writeAttribute("data-dojo-config", "async: true, parseOnLoad: true", null); writer.endElement("script"); encodeHeadResources(context, component); writer.endElement("head");//writer.startElement("head");在父类的encodeBegin里 } //获取皮肤参数并设置到cookie中 public static String getTheme(FacesContext context) { HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest(); String theme = request.getParameter(THEME_KEY); if (theme == null || theme.trim().length() < 1) { Cookie[] cookies = request.getCookies(); if (cookies != null && cookies.length > 0) { for (int i=0;i<cookies.length;i++) { Cookie cookie = cookies[i]; if (THEME_KEY.equals(cookie.getName())) { theme = cookie.getValue(); break; } } } } if (theme == null || theme.trim().length() < 1) { theme = DEFAULT_THEME; } HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse(); response.addCookie(new Cookie(THEME_KEY, theme)); return theme; } private void encodeHeadResources(FacesContext context, UIComponent component) throws IOException { ResponseWriter writer = context.getResponseWriter(); List<String> requires = new ArrayList<String>(); //require加入必需的dojo/parser requires.add("dojo/parser"); //解决皮肤切换需求 requires.add("dojo/dom-class"); UIViewRoot viewRoot = context.getViewRoot(); for (UIComponent resource : viewRoot.getComponentResources(context, "head")) { Map<String, Object> attributes = resource.getAttributes(); String name = (String) attributes.get("name"); //把引用的dojo库中的js文件,转换成require写法,不引入js文件 if (name.startsWith("dojo/") || name.startsWith("dijit/") || name.startsWith("dojox/")) { if (name.endsWith(".js")) { String path = name.substring(0, name.lastIndexOf(".")); if (!requires.contains(path)) requires.add(path); continue; } } resource.encodeAll(context); } //生成dojo require方式的代码 writer.startElement("script", component); writer.write("require(["); String tmp = ""; for (int i = 0; i < requires.size(); i++) { writer.write(tmp + "\"" + requires.get(i) + "\""); tmp = ", "; } ////解决皮肤切换需求 writer.write(", \"dojo/domReady!\"], function(parser, domClass) {"); writer.write("domClass.add(document.body, \"" + this.theme + "\");"); writer.write("});"); writer.endElement("script"); } }
删除ButtonRenderer.java和TextBoxRenderer.java中的代码:
@ResourceDependency(name = "dijit/themes/claro/claro.css", target = "head"),
将buttonTest.xhtml和textBoxTest.xhtml中的<body class="claro">改成<body>
这样改了以后,在首次访问页面时,会加载默认皮肤claro,可以通过在请求中加入dojo4j.theme=xxx改变皮肤,改了以后会保存在cookie中,持续有效。目前dojo提供的皮肤有四种:claro,tundra,soria,nihilo
查看生成的页面源代码可以看到发生的变化:
<link rel="stylesheet" href="/dojo4j/faces/javax.faces.resource/dijit/themes/tundra/tundra.css" />
<script> require([ "dojo/parser", "dojo/dom-class", "dijit/form/TextBox", "dijit/form/Button", "dojo/domReady!" ], function(parser, domClass) { domClass.add(document.body, "tundra"); }); </script>
下载代码