blob: 0f4cdb5c068f11302ba1904c509acb829938ac47 [file] [log] [blame]
// Copyright 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.apache.tapestry5.internal.services;
import org.apache.tapestry5.dom.Document;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import java.util.List;
import java.util.Set;
public class DocumentLinkerImpl implements DocumentLinker
{
private final List<String> scripts = CollectionFactory.newList();
private final StringBuilder scriptBlock = new StringBuilder();
private final Set<String> stylesheets = CollectionFactory.newSet();
private final List<IncludedStylesheet> includedStylesheets = CollectionFactory.newList();
private final boolean developmentMode;
public DocumentLinkerImpl(boolean productionMode)
{
developmentMode = !productionMode;
}
private class IncludedStylesheet
{
private final String url;
private final String media;
IncludedStylesheet(String url, String media)
{
this.url = url;
this.media = media;
}
void add(Element head, int index)
{
head.elementAt(index, "link",
"href", url,
"rel", "stylesheet",
"type", "text/css",
"media", media);
}
}
public void addStylesheetLink(String styleURL, String media)
{
if (stylesheets.contains(styleURL)) return;
includedStylesheets.add(new IncludedStylesheet(styleURL, media));
stylesheets.add(styleURL);
}
public void addScriptLink(String scriptURL)
{
if (scripts.contains(scriptURL)) return;
scripts.add(scriptURL);
}
public void addScript(String script)
{
if (InternalUtils.isBlank(script)) return;
scriptBlock.append(script);
scriptBlock.append("\n");
}
/**
* Updates the supplied Document, locating the html/body element and adding script links (to the top) and a script
* block (to the end).
*
* @param document to be updated
*/
public void updateDocument(Document document)
{
Element root = document.getRootElement();
// This can happen due to a catastrophic rendering error, such as a missing page template.
if (root == null) return;
// This only applies when the document is an HTML document. This may need to change in the
// future, perhaps configurable, to allow for html and xhtml and perhaps others. Does SVG
// use stylesheets?
if (!root.getName().equals("html")) return;
int stylesheets = includedStylesheets.size();
if (stylesheets > 0)
{
Element head = root.find("head");
if (head == null) head = root.elementAt(0, "head");
for (int i = 0; i < stylesheets; i++)
includedStylesheets.get(i).add(head, i);
}
Element body = root.find("body");
if (body == null) return;
// TAPESTRY-2364
for (String scriptURL : scripts)
{
body.element("script", "src", scriptURL, "type", "text/javascript");
}
boolean blockNeeded = (developmentMode && !scripts.isEmpty()) || scriptBlock.length() > 0;
if (blockNeeded)
{
Element e = body.element("script", "type", "text/javascript");
e.raw("\n<!--\n");
if (developmentMode)
e.text("Tapestry.DEBUG_ENABLED = true;\n");
e.text("Tapestry.onDOMLoaded(function() {\n");
e.text(scriptBlock.toString());
e.text("});\n");
e.raw("// -->\n");
}
}
}