module AssetTags include Radiant::Taggable class TagError < StandardError; end %w{top_padding width height caption asset_file_name asset_content_type asset_file_size id filename image flash thumbnail url link extension if_content_type page:title page:url}.each do |name| deprecated_tag "assets:#{name}", :substitute => "asset:#{name}", :deadline => '2.0' end Asset.known_types.each do |known_type| deprecated_tag "assets:if_#{known_type}", :substitute => "asset:if_#{known_type}", :deadline => '2.0' deprecated_tag "assets:unless_#{known_type}", :substitute => "asset:unless_#{known_type}", :deadline => '2.0' end desc %{ The namespace for referencing images and assets. *Usage:*
...
} tag 'asset' do |tag| tag.locals.asset = find_asset unless tag.attr.empty? tag.expand end desc %{ Cycles through all assets attached to the current page. This tag does not require the name atttribute, nor do any of its children. Use the @limit@ and @offset@ attribute to render a specific number of assets. Use @by@ and @order@ attributes to control the order of assets. Use @extensions@ attribute to specify which assets to be rendered. *Usage:*
...
} tag 'assets' do |tag| tag.expand end tag 'assets:each' do |tag| options = tag.attr.dup tag.locals.assets = tag.locals.page.assets.scoped(assets_find_options(tag)) tag.render('asset_list', tag.attr.dup, &tag.block) end # General purpose paginated asset lister. Very useful dryness. # Tag.locals.assets must be defined but can be empty. tag 'asset_list' do |tag| raise TagError, "r:asset_list: no assets to list" unless tag.locals.assets options = tag.attr.symbolize_keys result = [] paging = pagination_find_options(tag) assets = paging ? tag.locals.assets.paginate(paging) : tag.locals.assets.all assets.each do |asset| tag.locals.asset = asset result << tag.expand end if paging && assets.total_pages > 1 tag.locals.paginated_list = assets result << tag.render('pagination', tag.attr.dup) end result end desc %{ References the first asset attached to the current page. *Usage:*
...
} tag 'assets:first' do |tag| if tag.locals.asset = tag.locals.page.assets.first tag.expand end end desc %{ Renders the contained elements only if the current contextual page has one or more assets. The @min_count@ attribute specifies the minimum number of required assets. You can also filter by extensions with the @extensions@ attribute. *Usage:*
...
} tag 'if_assets' do |tag| count = tag.attr['min_count'] && tag.attr['min_count'].to_i || 1 assets = tag.locals.page.assets.count(:conditions => assets_find_options(tag)[:conditions]) tag.expand if assets >= count end desc %{ The opposite of @@. } tag 'unless_assets' do |tag| count = tag.attr['min_count'] && tag.attr['min_count'].to_i || 1 assets = tag.locals.page.assets.count(:conditions => assets_find_options(tag)[:conditions]) tag.expand unless assets >= count end # Resets the page Url and title within the asset tag [:title, :url].each do |method| tag "asset:page:#{method.to_s}" do |tag| tag.locals.page.send(method) end end desc %{ Renders the value for a top padding for the image. Put the image in a container with specified height and using this tag you can vertically align the image within it's container. *Usage*:
*Working Example*:

      
  • <r:title />
} tag 'asset:top_padding' do |tag| asset, options = asset_and_options(tag) raise TagError, 'Asset is not an image' unless asset.image? raise TagError, "'container' attribute required" unless options['container'] size = options['size'] ? options.delete('size') : 'icon' container = options.delete('container') img_height = asset.height(size) (container.to_i - img_height.to_i)/2 end ['height','width'].each do |dimension| desc %{ Renders the #{dimension} of the asset. } tag "asset:#{dimension}" do |tag| asset, options = asset_and_options(tag) unless asset.dimensions_known? raise TagError, "Can't determine #{dimension} for this Asset. It may not be a supported type." end size = options['size'] ? options.delete('size') : 'original' asset.send(dimension, size) end end desc %{ Returns a string representing the orientation of the asset, which must be an image. Can be 'horizontal', 'vertical' or 'square'. } tag 'asset:orientation' do |tag| asset, options = asset_and_options(tag) raise TagError, 'Asset is not an image' unless asset.image? size = options['size'] ? options.delete('size') : 'original' asset.orientation(size) end desc %{ Returns the aspect ratio of the asset, which must be an image. } tag 'asset:aspect' do |tag| asset, options = asset_and_options(tag) raise TagError, 'Asset is not an image' unless asset.image? size = options['size'] ? options.delete('size') : 'original' asset.aspect(size) end desc %{ Renders the containing elements only if the asset's content type matches the regular expression given in the @matches@ attribute. If the @ignore_case@ attribute is set to false, the match is case sensitive. By default, @ignore_case@ is set to true. The @name@ or @id@ attribute is required on the parent tag unless this tag is used in @asset:each@. *Usage:*
...
} tag 'asset:if_content_type' do |tag| options = tag.attr.dup # XXX build_regexp_for comes from StandardTags regexp = build_regexp_for(tag,options) asset_content_type = tag.locals.asset.asset_content_type tag.expand unless asset_content_type.match(regexp).nil? end #TODO: could use better docs for Asset#other? case explaining what types it covers Asset.known_types.each do |known_type| desc %{ Renders the contents only of the asset is of the type #{known_type} } tag "asset:if_#{known_type}" do |tag| tag.expand if find_asset(tag, tag.attr.dup).send("#{known_type}?".to_sym) end desc %{ Renders the contents only of the asset is not of the type #{known_type} } tag "asset:unless_#{known_type}" do |tag| tag.expand unless find_asset(tag, tag.attr.dup).send("#{known_type}?".to_sym) end end [:title, :caption, :asset_file_name, :extension, :asset_content_type, :asset_file_size, :id].each do |method| desc %{ Renders the @#{method.to_s}@ attribute of the asset } tag "asset:#{method.to_s}" do |tag| asset, options = asset_and_options(tag) asset.send(method) rescue nil end end tag 'asset:name' do |tag| tag.render('asset:title', tag.attr.dup) end tag 'asset:filename' do |tag| asset, options = asset_and_options(tag) asset.asset_file_name rescue nil end desc %{ Renders an image tag for the asset. Using the optional @size@ attribute, different sizes can be display. "thumbnail" and "icon" sizes are built in, but custom ones can be set using by changing assets.addition_thumbnails in the Radiant::Config settings. *Usage:*
} tag 'asset:image' do |tag| tag.locals.asset, options = asset_and_options(tag) if tag.locals.asset.image? size = options['size'] ? options.delete('size') : 'original' alt = "alt='#{tag.locals.asset.title}'" unless tag.attr['alt'] attributes = options.inject('') { |s, (k, v)| s << %{#{k.downcase}="#{v}" } }.strip attributes << alt unless alt.nil? url = tag.locals.asset.thumbnail(size) %{} rescue nil end end desc %{ Embeds a flash-movie in a cross-browser-compatible fashion using only HTML If no width and height attributes are given it will use the intrinsic dimensions of the swf file *Usage:*
Fallback content
*Example with text fallback:*

        Sorry, you need to have flash installed, get it here
    
*Example with image fallback and explicit dimensions:*

        
      
} tag 'asset:flash' do |tag| asset, options = asset_and_options(tag) if tag.locals.asset.flash? url = asset.thumbnail('original') dimensions = [(tag.attr['width'] || asset.width),(tag.attr['height'] || asset.height)] swf_embed_markup url, dimensions, tag.expand end end desc %{ Renders the url for the asset. If the asset is an image, the size attribute can be used to generate the url for that size. *Usage:*
} tag 'asset:url' do |tag| asset, options = asset_and_options(tag) size = options['size'] ? options.delete('size') : 'original' asset.thumbnail(size) rescue nil end desc %{ Renders a link to the asset. If the asset is an image, the size attribute can be used to generate a link to that size. *Usage:*
} tag 'asset:link' do |tag| asset, options = asset_and_options(tag) size = options['size'] ? options.delete('size') : 'original' text = options['text'] || asset.title anchor = options['anchor'] ? "##{options.delete('anchor')}" : '' attributes = options.inject('') { |s, (k, v)| s << %{#{k.downcase}="#{v}" } }.strip attributes = " #{attributes}" unless attributes.empty? text = tag.double? ? tag.expand : text url = asset.thumbnail(size) %{#{text}} rescue nil end private def asset_and_options(tag) options = tag.attr.dup [find_asset(tag, options), options] end def find_asset(tag, options) tag.locals.asset ||= if title = (options.delete('name') || options.delete('title')) Asset.find_by_title(title) elsif id = options.delete('id') Asset.find_by_id(id) end tag.locals.asset || raise(TagError, "Asset not found.") end def assets_find_options(tag) attr = tag.attr.symbolize_keys extensions = attr[:extensions] && attr[:extensions].split('|') || [] conditions = unless extensions.blank? # this is soon to be removed in favour of asset types [ extensions.map { |ext| "assets.asset_file_name LIKE ?"}.join(' OR '), *extensions.map { |ext| "%.#{ext}" } ] else nil end by = attr[:by] || 'page_attachments.position' order = attr[:order] || 'asc' options = { :order => "#{by} #{order}", :limit => attr[:limit] || nil, :offset => attr[:offset] || nil, :conditions => conditions } end def swf_embed_markup(url, dimensions, fallback_content) width, height = dimensions %{ #{fallback_content} } end end