Grails
  1. Grails
  2. GRAILS-4499

Add new tag for inserting resource dependencies into pages

    Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.0-M1
    • Component/s: None
    • Labels:
      None

      Description

      GSPs and taglibs (often in plugins) need to include resources in the output.

      We have the g:resource tag for creating URLs but we don't have a single tag that renders the appropriate <link> or <script> tags with smart autosensing of the type.

      E.g. for CSS you want it to write out a <link href="......" type="text/css" rel="stylesheet"/> but for RSS and Atom you want different types and rel's, and JS resources should also be handled by the same tag but output a <script> tag the same way g:javascript does now.

      Centralizing this mechanism in core will then allow some advanced features in future - dependency resolution for resources. (Separate issue needed for that...)

        Activity

        Hide
        Marc Palmer added a comment -

        I have code for this already used in the new jQuery-ui plugin:

        class ResourceLinkTagLib {
            static namespace = "res"
        
            static writeAttrs( attrs, output) {
                // Output any remaining user-specified attributes
                attrs.each { k, v ->
                   output << k
                   output << '="'
                   output << v.encodeAsHTML()
                   output << '" '    
                }
            }
        
            static LINK_WRITERS = [
                js: { url, constants, attrs ->
                    def o = new StringBuilder()
                    o << "<script src=\"${url.encodeAsHTML()}\" "
        
                    // Output info from the mappings
                    writeAttrs(constants, o)
                    writeAttrs(attrs, o)
        
                    o << '></script>'
                    return o    
                },
                
                link: { url, constants, attrs ->
                    def o = new StringBuilder()
                    o << "<link href=\"${url.encodeAsHTML()}\" "
        
                    // Output info from the mappings
                    writeAttrs(constants, o)
                    writeAttrs(attrs, o)
        
                    o << '/>'
                    return o
                }
            ]
            
            static RESOURCE_MAPPINGS = [
                css:[type:"text/css", rel:'stylesheet'],
                rss:[type:'application/rss+xml', rel:'alternate'], 
                atom:[type:'application/atom+xml', rel:'alternate'], 
                favicon:[type:'image/x-icon', rel:'shortcut icon'],
                appleicon:[type:'image/x-icon', rel:'apple-touch-icon'],
                js:[writer:'js', type:'text/javascript']
            ]
        
            def resourceLink = { attrs ->
                def t = attrs.remove('type')
                def typeInfo = [:] + RESOURCE_MAPPINGS[t]
                if (!typeInfo) {
                    throwTagError "Unknown resourceLink type: ${t}"
                }
                def url = g.resource(plugin:attrs.remove('plugin'), dir:attrs.remove('dir'), file:attrs.remove('file'))
                
                def writerName = typeInfo.remove('writer')
                def writer = LINK_WRITERS[writerName ?: 'link']
                out << writer(url, typeInfo, attrs)
            }
        }
        
        Show
        Marc Palmer added a comment - I have code for this already used in the new jQuery-ui plugin: class ResourceLinkTagLib { static namespace = "res" static writeAttrs( attrs, output) { // Output any remaining user-specified attributes attrs.each { k, v -> output << k output << '="' output << v.encodeAsHTML() output << '" ' } } static LINK_WRITERS = [ js: { url, constants, attrs -> def o = new StringBuilder() o << "<script src=\" ${url.encodeAsHTML()}\ " " // Output info from the mappings writeAttrs(constants, o) writeAttrs(attrs, o) o << '></script>' return o }, link: { url, constants, attrs -> def o = new StringBuilder() o << "<link href=\" ${url.encodeAsHTML()}\ " " // Output info from the mappings writeAttrs(constants, o) writeAttrs(attrs, o) o << '/>' return o } ] static RESOURCE_MAPPINGS = [ css:[type: "text/css" , rel:'stylesheet'], rss:[type:'application/rss+xml', rel:'alternate'], atom:[type:'application/atom+xml', rel:'alternate'], favicon:[type:'image/x-icon', rel:'shortcut icon'], appleicon:[type:'image/x-icon', rel:'apple-touch-icon'], js:[writer:'js', type:'text/javascript'] ] def resourceLink = { attrs -> def t = attrs.remove('type') def typeInfo = [:] + RESOURCE_MAPPINGS[t] if (!typeInfo) { throwTagError "Unknown resourceLink type: ${t}" } def url = g.resource(plugin:attrs.remove('plugin'), dir:attrs.remove('dir'), file:attrs.remove('file')) def writerName = typeInfo.remove('writer') def writer = LINK_WRITERS[writerName ?: 'link'] out << writer(url, typeInfo, attrs) } }
        Hide
        Marc Palmer added a comment -

        This was covered by the g:external tag.

        Show
        Marc Palmer added a comment - This was covered by the g:external tag.

          People

          • Assignee:
            Marc Palmer
            Reporter:
            Marc Palmer
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development