module AssetTags include TrustyCms::Taggable include ActionView::Helpers::TagHelper include ActionView::Helpers::AssetTagHelper 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 desc %{ The namespace for referencing images and assets. *Usage:*
...
}
tag 'asset' do |tag|
tag.locals.asset = find_asset(tag, tag.attr) 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, "'container' attribute required" unless options['container']
size = options['size'] ? options.delete('size') : 'icon'
raise TagError, "asset #{tag.locals.asset.title} has no '#{size}' thumbnail" unless tag.locals.asset.style?(size)
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 imageable.
(ie, it is an image or it has been processed to produce an image).
Can be 'horizontal', 'vertical' or 'square'.
}
tag 'asset:orientation' do |tag|
asset, options = asset_and_options(tag)
size = options['size'] ? options.delete('size') : 'original'
raise TagError, "asset #{tag.locals.asset.title} has no '#{size}' thumbnail" unless tag.locals.asset.style?(size)
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)
size = options['size'] ? options.delete('size') : 'original'
raise TagError, "asset #{tag.locals.asset.title} has no '#{size}' thumbnail" unless tag.locals.asset.style?(size)
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
[: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
by changing `assets.thumbnails.[type]` in the TrustyCms::Config settings.
*Usage:*
}
tag 'asset:image' do |tag|
tag.locals.asset, options = image_asset_and_options(tag)
return "Error: This image cannot be found" if tag.locals.asset == nil
size = options.delete('size') || 'original'
raise TagError, "asset #{tag.locals.asset.title} has no '#{size}' thumbnail" unless tag.locals.asset.style?(size)
options['alt'] ||= tag.locals.asset.title
url = tag.locals.asset.thumbnail(size)
ActionController::Base.helpers.image_tag(url, options)
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 image_asset_and_options(tag)
options = tag.attr.dup
[find_image_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 find_image_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 || nil
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
end