The correct approach is to modify the DocumentLinker service (which is
internal) to place the <script> tags where you want.

On Thu, Oct 21, 2010 at 1:52 AM, janp <[email protected]> wrote:
>
> This post describes a service, that enables Tapestry to append JavaScript
> files and script parts at the end of a html file. Script files and scripts
> can be "dropped into the service" from any page class or component and will
> be rendered in that order (FIFO) at the end of the page.
>
> Upgrade Tapestry 5.0.x to Tapestry 5.1. loads included JavaScript files in
> the HTML head. Reasons are discussed in the Upgrade Notes:
> http://tapestry.apache.org/tapestry5.1/upgrade.html
> project-wide release notes. They told me that in fix for bug TAP5-544:
> Firstly, JavaScript libraries would have to move (back) to the head,
> permanently, no configuration [...].
> Maybe I did not understand the real concern, but: Why isn't it up to the
> developer to decide where to place script files?
> I decided to write a component that appends my script files at the end of my
> html files. The most important reason for this descicion is, that--following
> Yahoo's performance guidelines--I'd like to first load my HTML DOM before
> loading the script files.
>
> Write a Service to Collect Files to Append
> We need an Interface to be able to use the perthread scope (more about
> scoypes: "a per-thread instance is created on demand, behind a shared
> proxy").
> The Interface just consists of 4 methods. 2 to add Script files and Scripts
> to the list and 2 to get the lists when they should be rendered:
> public interface IAppendedScriptsService {
>
>    /**
>     * Add a script file to the list of script files to append.
>     *
>     * @param scriptFile
>     */
>    public void addScriptFile(String scriptFile);
>
>    /**
>     * Add a script to the list of scripts to append.
>     *
>     * @param script
>     */
>    public void addScript(String script);
>
>    /**
>     * Returns a list with script files to append. Needs to be a list to
> preserve order of script files.
>     *
>     * @return list with script files to append.
>     */
>    public List getScriptFiles();
>
>    /**
>     * Returns a list with scripts to append. Needs to be a list to preserve
> order of scripts.
>     *
>     * @return list with scripts to append.
>     */
>    public List getScripts();
> }
> The implementation of the Interface could looks like the following block.
> Don't forget to set the scope to perthread.
> @Scope(value = ScopeConstants.PERTHREAD)
> public class AppendedScriptsService implements IAppendedScriptsService {
>
>    private final List scriptFiles = new ArrayList();
>    private final List scripts = new ArrayList();
>
>   �...@override
>    public void addScriptFile(String scriptFile) {
>        this.scriptFiles.add(scriptFile);
>    }
>
>   �...@override
>    public void addScript(String script) {
>        this.scripts.add(script);
>    }
>
>   �...@override
>    public List getScriptFiles() {
>        return this.scriptFiles;
>    }
>
>   �...@override
>    public List getScripts() {
>        return this.scripts;
>    }
>
> }
> Build the Component
> The Component was easy to write. It consists of just one method to render
> the scripts:
>    // Inject the service we just wrote.
>   �...@inject
>    private IAppendedScriptsService appendedScriptsService;
>
>    // This method is called when component should be rendered. (Markup
> writer infos here)
>    void beginRender(MarkupWriter markupWriter) {
>
>        // Output script files.
>        if (!this.appendedScriptsService.getScriptFiles().isEmpty()) {
>            for (final String file :
> this.appendedScriptsService.getScriptFiles()) {
>                // There might be another (tapestry conform way) to create
> the source link. My way is
>                String fileUrl = "MyAssetsServerURL".resolveRelative(file);
>                markupWriter.element("script", "type", "text/javascript",
> "src", fileUrl);
>                markupWriter.end();
>            }
>        }
>
>        // Output script snippets.
>        if (!this.appendedScriptsService.getScripts().isEmpty()) {
>            for (final String script :
> this.appendedScriptsService.getScripts()) {
>                markupWriter.element("script", "type", "text/javascript");
>                markupWriter.getElement().text(script);
>                markupWriter.end();
>            }
>        }
>
>    }
> That's all to implement. Just one last step to make this run:
>
> Activate Service in AppModule
> To activate your Service, following method must be inserted into
> AppModule.java (or just insert the binder-line if there is already such a
> method):
> public static void bind(ServiceBinder binder) {
>  binder.bind(IAppendedScriptsService.class, AppendedScriptsService.class);
> }
> User Component
> To use this Component, you just have to add this into a class of a page or
> component:
>
> @Inject
> private IAppendedScriptsService appendedScriptsService;
>
> /**
> * Append JavaScripts
> **/
> void setupRender() {
>    this.appendedScriptsService.addScriptFile("UrlToScript");
>    appendedScriptsService.addScript("var x = 'cool';");
> }
> The order of scripts and script files is preserved.
>
> Do you have any comments? Please, let's discuss this.
>
>
>
>
> --
> View this message in context: 
> http://tapestry.1045711.n5.nabble.com/Append-JavaScript-at-the-end-of-my-html-file-Component-for-Tapestry-5-1-tp3230082p3230082.html
> Sent from the Tapestry - Dev mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>



-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to