Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove generic Tapestry JavaScript and CSS

I have created a new Tapestry 5.3 project using Maven. I noticed that Tapestry adds tons of different JS and CSS files to all pages:

<link type="text/css" rel="stylesheet" href="/tutorial1/assets/1.0-SNAPSHOT-DEV/tapestry/default.css"/>
<link type="text/css" rel="stylesheet" href="/tutorial1/assets/1.0-SNAPSHOT-DEV/ctx/layout/layout.css"/>
<link type="text/css" rel="stylesheet" href="/tutorial1/assets/1.0-SNAPSHOT-DEV/tapestry/tapestry-console.css"/>
<link type="text/css" rel="stylesheet" href="/tutorial1/assets/1.0-SNAPSHOT-DEV/tapestry/t5-alerts.css"/>
<link type="text/css" rel="stylesheet" href="/tutorial1/assets/1.0-SNAPSHOT-DEV/tapestry/tree.css"/>
<script src="/tutorial1/assets/1.0-SNAPSHOT-DEV/tapestry/underscore_1_3_3.js" type="text/javascript"></script>
<script src="/tutorial1/assets/1.0-SNAPSHOT-DEV/tapestry/scriptaculous_1_9_0/prototype.js" type="text/javascript"></script>

And many, MANY more...

Are these required for my site to work properly? If not, how can I remove them? I am pretty comfortable to write JS myself and I do not need Tapestry to add anything for me.

like image 837
Eleeist Avatar asked Apr 23 '26 13:04

Eleeist


2 Answers

It's funny: Tapestry provides very rich functionality to override default service behavior but not in this case. The main culprit JavaScriptSupport is created on the fly and can't be decorated.

MarkupRendererFilter javaScriptSupport = new MarkupRendererFilter() {
        public void renderMarkup(MarkupWriter writer, MarkupRenderer renderer) {
            DocumentLinker linker = environment.peekRequired(DocumentLinker.class);
            //Surprise!;) 
            JavaScriptSupportImpl support = new JavaScriptSupportImpl(linker, javascriptStackSource, javascriptStackPathConstructor);
            environment.push(JavaScriptSupport.class, support);
            renderer.renderMarkup(writer);
            environment.pop(JavaScriptSupport.class);
            support.commit();
        }
    };

So the only way is to patch sources (as we did many times), or to try to override the javascriptStackSource which goes as param to JavaScriptSupportImpl:

Your AppModule.java

@Decorate(serviceInterface = JavaScriptStackSource.class)
public JavaScriptStackSource decorateJavaScriptStackSource(JavaScriptStackSource original) {
    return new MyJavaScriptStackSource(original);
}

MyJavaScriptStackSource.java

public class MyJavaScriptStackSource implements JavaScriptStackSource {
// This bunch of stacks comes from got5
private Set<String> SKIP = new HashSet<String>(Arrays.asList("Slider", "AjaxUploadStack", "DataTableStack", "FormFragmentSupportStack", "FormSupportStack",
        "SuperfishStack", "JQueryDateFieldStack", "GalleryStack"));

private class JavaScriptStackWraper implements JavaScriptStack {
    private final JavaScriptStack original;

    JavaScriptStackWraper(JavaScriptStack original) {
        if (original != null) {
            System.out.println("Wrap " + original.getClass().getName());
        }
        this.original = original;
    }

    @Override
    public List<String> getStacks() {
        return original != null ? original.getStacks() : Collections.<String>emptyList();
    }

    @Override
    public List<Asset> getJavaScriptLibraries() {
        return original != null ? original.getJavaScriptLibraries() : Collections.<Asset>emptyList();
    }

    // Always return empty list
    @Override
    public List<StylesheetLink> getStylesheets() {
        return Collections.<StylesheetLink>emptyList();
    }

    @Override
    public String getInitialization() {
        return original != null ? original.getInitialization() : null;
    }
}

private final JavaScriptStackSource original;

public MyJavaScriptStackSource(JavaScriptStackSource original) {
    this.original = original;
}

@Override
public JavaScriptStack getStack(String name) {
    JavaScriptStack stack = original.getStack(name);
    if (!SKIP.contains(stack.getClass().getSimpleName())) {
        return new JavaScriptStackWraper(stack);
    }
    return new JavaScriptStackWraper(null);
}

@Override
public List<String> getStackNames() {
    return original.getStackNames();
}

}

It's a big piece of shitty code but it works.. I'd like to have more control of whats displaying in my pages in Tapestry.

like image 62
xl0e Avatar answered Apr 25 '26 03:04

xl0e


Part of the advantage of Tapestry is the number of components that provide DHTML and Ajax behaviors out of the box without writing any JavaScript, but just configuring components.

It is possible to disable this, but that means many components you might like to use, such as Zone, will be broken. Likewise, all client-side input validation will be gone. I do have clients that have done this, but it is not a small undertaking.

Basically, you can override Tapestry's "core" JavaScriptStack. There isn't a FAQ for this, because it is not frequently asked. It is also not for an absolute beginner, more a journeyman thing (it is relatively easy to override things in Tapestry due to its inversion of control container, but knowing WHAT to override is trickier).

In any case, Tapestry 5.4 is well underway and is changing Tapestry's JavaScript to be much lighter and much more modular, as well as giving you the choice between Prototype (mostly for compatibility in existing Tapestry projects) or jQuery. Even then, however, there will be some amount of JavaScript built into the framework.

like image 29
Howard M. Lewis Ship Avatar answered Apr 25 '26 02:04

Howard M. Lewis Ship



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!