Click
  1. Click
  2. CLK-501

Add first class support for HTML Head resources such as Javascript and CSS

    Details

    • Type: New Feature New Feature
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.1.0
    • Component/s: core
    • Labels:
      None

      Description

      Currently Click supports HTML imports by overriding the method #getHtmlImports.

      This method is string based which makes it difficult to support advanced features such as templating, conditional imports, resource versioning etc.

      This feature request proposes to introduce first class HTML header resource classes including Javascript, JavascriptImport, CssImport and Css.

      Further a new method should be added to the Control interface: 'public List getHtmlHeaders' which returns a list of the Page or Control's HTML HEAD entries.

      This makes it possible to modify the Javascript and CSS imports without overriding a Control.

        Activity

        Bob Schellink made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]
        Hide
        Bob Schellink added a comment -

        This feature is implemented as part of 2.1.0

        Show
        Bob Schellink added a comment - This feature is implemented as part of 2.1.0
        Henri Yandell made changes -
        Field Original Value New Value
        Project Import Fri Mar 20 14:11:32 PDT 2009 [ 1237583492744 ]
        Hide
        Bob Schellink added a comment -

        Made the following changes:

        1. renamed method getHtmlHeaders to getHeadElements
        1. added new package 'element' and moved utility classes to this package
        1. the following elements were added: Element, ResourceElement, CssImport, CssStyle, JsImport, JsScript. ResourceElement is new and is the super class of Javascript and CSS elements. ResourceElement could also be used as the super class of an Image element.
        1. new PageImports variables $headElements and $jsElements. The other variables still exist for backward compatibility
        Show
        Bob Schellink added a comment - Made the following changes: renamed method getHtmlHeaders to getHeadElements added new package 'element' and moved utility classes to this package the following elements were added: Element, ResourceElement, CssImport, CssStyle, JsImport, JsScript. ResourceElement is new and is the super class of Javascript and CSS elements. ResourceElement could also be used as the super class of an Image element. new PageImports variables $headElements and $jsElements. The other variables still exist for backward compatibility
        Hide
        Bob Schellink added a comment -

        I also thought about leveraging onRender, however users can skip this phase by returning false from an action listener.

        At least 3 approaches exist to add elements to the HeadElements List.

        1. in the Page/Control constructor
        2. overriding getHeadElements using lazy loading
        3. in onInit and onProcess. However in this case the HeadElements List must be nullified in the onDestroy callback. This ensures no memory leaks exist with stateful pages

        > The Container controls then iterate through their children doing the same

        My current approach is not to let the Container return their child control Head elements. Instead PageImports recursively process each Control. The reason that each Control and Container return only their own List of Head Elements, is to introduce the ability to dynamically add/remove a Control's Javascript and CSS at runtime.

        Introducing Element will also raise the question of how it ties in with Control. Should AbstractControl extend Element?

        Another thing to keep in mind is that TitleElement and CacheElement can also be supported through a BorderPage and custom Velocity variables instead of HeadElements.

        Show
        Bob Schellink added a comment - I also thought about leveraging onRender, however users can skip this phase by returning false from an action listener. At least 3 approaches exist to add elements to the HeadElements List. in the Page/Control constructor overriding getHeadElements using lazy loading in onInit and onProcess. However in this case the HeadElements List must be nullified in the onDestroy callback. This ensures no memory leaks exist with stateful pages > The Container controls then iterate through their children doing the same My current approach is not to let the Container return their child control Head elements. Instead PageImports recursively process each Control. The reason that each Control and Container return only their own List of Head Elements, is to introduce the ability to dynamically add/remove a Control's Javascript and CSS at runtime. Introducing Element will also raise the question of how it ties in with Control. Should AbstractControl extend Element? Another thing to keep in mind is that TitleElement and CacheElement can also be supported through a BorderPage and custom Velocity variables instead of HeadElements.
        Hide
        Malcolm Edgar added a comment -

        I have this feeling, that what I am advocating is something you proposed earlier.

        I haven't thought through the integration. Off the top of my head I would imagine, controls would have the same methods:

        List<Element> getHeadElements()

        List<Element> getJsElements()

        The ClickServlet processes the page controls calling their onRender() methods. The Container controls then iterate through their children doing the same. At this point it is up to the individual control to add its Elements (Head, JS) to the parent Page's corresponding HeadElements or JsElements.

        These page elements would automatically be added to the Velocity context / JSP request attributes before rendering.

        We could introduce some sort of adaptor mechanism to support depreciated getHtmlImports() methods.

        regards Malcolm Edgar

        Show
        Malcolm Edgar added a comment - I have this feeling, that what I am advocating is something you proposed earlier. I haven't thought through the integration. Off the top of my head I would imagine, controls would have the same methods: List<Element> getHeadElements() List<Element> getJsElements() The ClickServlet processes the page controls calling their onRender() methods. The Container controls then iterate through their children doing the same. At this point it is up to the individual control to add its Elements (Head, JS) to the parent Page's corresponding HeadElements or JsElements. These page elements would automatically be added to the Velocity context / JSP request attributes before rendering. We could introduce some sort of adaptor mechanism to support depreciated getHtmlImports() methods. regards Malcolm Edgar
        Hide
        Bob Schellink added a comment -

        Hi Malcolm,

        I like the idea of a more generic approach to HTML headers and housing these classes in their own package.

        How do you see Page and Control imports integrate though? For example will #getHeadElements return the Control imports as well? Or will Control imports be specified separately with the $cssIncludes and jsIncludes variables?

        kind regards

        bob

        Show
        Bob Schellink added a comment - Hi Malcolm, I like the idea of a more generic approach to HTML headers and housing these classes in their own package. How do you see Page and Control imports integrate though? For example will #getHeadElements return the Control imports as well? Or will Control imports be specified separately with the $cssIncludes and jsIncludes variables? kind regards bob
        Hide
        Malcolm Edgar added a comment -

        Another useful Element would be MetaElement for header meta data tags which are used by search engines.

        This stuff should probably go into its own package: ogr.apache.click.element

        Show
        Malcolm Edgar added a comment - Another useful Element would be MetaElement for header meta data tags which are used by search engines. This stuff should probably go into its own package: ogr.apache.click.element
        Hide
        Malcolm Edgar added a comment -

        In terms of a design we could introduce a HTML Element class which can be used for:

        • TitleElement
        • CssStyleElement
        • CssImportElement
        • JsScriptElement
        • JsImportElement

        A Page could expose the methods:

        List<Element> getHeadElements()

        List<Element> getJsElements()

        In the page template users would do something like:
        <html>
        <head>
        #foreach ($element in $headElements)
        $element
        #end
        </head>
        <body>

        <body>
        #foreach ($element in $jsElements)
        $element
        #end

        Show
        Malcolm Edgar added a comment - In terms of a design we could introduce a HTML Element class which can be used for: TitleElement CssStyleElement CssImportElement JsScriptElement JsImportElement A Page could expose the methods: List<Element> getHeadElements() List<Element> getJsElements() In the page template users would do something like: <html> <head> #foreach ($element in $headElements) $element #end </head> <body> <body> #foreach ($element in $jsElements) $element #end
        Bob Schellink created issue -

          People

          • Assignee:
            Bob Schellink
            Reporter:
            Bob Schellink
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development