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 @
*Working Example*:
-
}
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')
((container.to_i - asset.height(size).to_i)/2).to_s
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
%{
}
end
end