# Methods added to this helper will be available to all templates in the # application. module ApplicationHelper include PermissionName include LightboxHelper include ThickboxHelper include BoxesHelper include FormsHelper include AssetsHelper include BlockHelper include DatesHelper include FolderHelper include ProfileEditorHelper include DisplayHelper include AccountHelper def locale (@page && !@page.language.blank?) ? @page.language : FastGettext.locale end # Displays context help. You can pass the content of the help message as the # first parameter or using template code inside a block passed to this # method. *Note*: the block is ignored if content is not # nil # # The method returns the text generated, so you can also use it inside a # <%= ... %> # # Follow some examples ... # # Passing the text as argument: # # <% help 'This your help message' %> # # Using a block: # # <% help do %> # This is the help message to be displayed. It can contain any HTML you # want: bold, italic. It can also contain calls # to any Rails helper, like <%= link_to 'home', :controller => 'home' %>. # <% end %> # # You can also pass an optional argument to force the use of textile in your # help message: # # <% help nil, :textile do %> # You can also use *textile*! # <% end %> # # or, using the return of the method: # # <%= help 'this is your help message' %> # # Formally, the type argument can be :html (i.e. no # conversion of the input) or :textile (converts the message, in # textile, into HTML). It defaults to :html. # # TODO: implement correcly the 'Help' button click def help(content = nil, link_name = nil, options = {}, &block) link_name ||= _('Help') @help_message_id ||= 1 help_id = "help_message_#{@help_message_id}" if content.nil? return '' if block.nil? content = capture(&block) end if options[:type] == :textile content = RedCloth.new(content).to_html end options[:class] = '' if ! options[:class] options[:class] += ' button icon-help' # with-text # TODO: implement this button, and add style='display: none' to the help # message DIV button = link_to_function(content_tag('span', link_name), "Element.show('#{help_id}')", options ) close_button = content_tag("div", link_to_function(_("Close"), "Element.hide('#{help_id}')", :class => 'close_help_button')) text = content_tag('div', button + content_tag('div', content_tag('div', content) + close_button, :class => 'help_message', :id => help_id, :style => 'display: none;'), :class => 'help_box') unless block.nil? concat(text, block.binding) end text end # alias for help(content, :textile). You can pass a block in the # same way you would do if you called help directly. def help_textile(content = nil, link_name = nil, options = {}, &block) options[:type] = :textile help(content, link_name, options, &block) end # TODO: do something more useful here # TODO: test this helper # TODO: add an icon? # TODO: the command rake test:rcov didn't works because of this method. See what it's the problem def environment_identification content_tag('div', @environment.name, :id => 'environment_identification') end def link_to_cms(text, profile = nil, options = {}) profile ||= current_user.login link_to text, myprofile_path(:controller => 'cms', :profile => profile), options end def link_to_profile(text, profile = nil, options = {}) profile ||= current_user.login link_to text, profile_path(:profile => profile) , options end def link_to_homepage(text, profile = nil, options = {}) p = if profile Profile[profile] else user end link_to text, p.url, options end def link_if_permitted(link, permission = nil, target = nil) if permission.nil? || current_user.person.has_permission?(permission, target) link else nil end end def footer # FIXME: add some information from the environment [ content_tag('div', _('This is %s, version %s') % [ link_to(Noosfero::PROJECT, 'http://www.noosfero.com.br/'), Noosfero::VERSION]), ].join("\n") end # returns the current profile beign viewed. # # Make sure that you use this helper method only in contexts where there # should be a current profile (i.e. while viewing some profile's pages, or the # profile info, etc), because if there is no profile an exception is thrown. def profile @controller.send(:profile) end def category_color if @category.nil? "" else @category.top_ancestor.display_color end end def text_editor(object, method, filter_type_method = nil, options = {}) text_area(object, method, { :rows => 10, :cols => 64 }.merge(options)) end def hide(id) "Element.hide(#{id.inspect});" end def show(id) "Element.show(#{id.inspect});" end def toggle_panel(hide_label, show_label, id) hide_button_id = id + "-hide" show_button_id = id + "-show" result = "" result << button_to_function('open', show_label, show(id) + show(hide_button_id) + hide(show_button_id), :id => show_button_id, :class => 'show-button with-text', :style => 'display: none;' ) result < " " result << button_to_function('close', hide_label, hide(id) + hide(hide_button_id) + show(show_button_id), :id => hide_button_id, :class => 'hide-button with-text') result end def button(type, label, url, html_options = {}) the_class = 'with-text' if html_options.has_key?(:class) the_class << ' ' << html_options[:class] end button_without_text type, label, url, html_options.merge(:class => the_class) end def button_without_text(type, label, url, html_options = {}) the_class = "button icon-#{type}" if html_options.has_key?(:class) the_class << ' ' << html_options[:class] end the_title = html_options[:title] || label link_to(' '+content_tag('span', label), url, html_options.merge(:class => the_class, :title => the_title)) end def button_to_function(type, label, js_code, html_options = {}, &block) html_options[:class] = "button with-text" unless html_options[:class] html_options[:class] << " icon-#{type}" link_to_function(label, js_code, html_options, &block) end def button_to_function_without_text(type, label, js_code, html_options = {}, &block) html_options[:class] = "" unless html_options[:class] html_options[:class] << " button icon-#{type}" link_to_function(content_tag('span', label), js_code, html_options, &block) end def button_to_remote(type, label, options, html_options = {}) html_options[:class] = "button with-text" unless html_options[:class] html_options[:class] << " icon-#{type}" link_to_remote(label, options, html_options) end def button_to_remote_without_text(type, label, options, html_options = {}) html_options[:class] = "" unless html_options[:class] html_options[:class] << " button icon-#{type}" link_to_remote(content_tag('span', label), options, html_options.merge(:title => label)) end def icon(icon_name, html_options = {}) the_class = "button #{icon_name}" if html_options.has_key?(:class) the_class << ' ' << html_options[:class] end content_tag('div', '', html_options.merge(:class => the_class)) end def icon_button(type, text, url, html_options = {}) the_class = "button icon-button icon-#{type}" if html_options.has_key?(:class) the_class << ' ' << html_options[:class] end link_to(content_tag('span', text), url, html_options.merge(:class => the_class, :title => text)) end def button_bar(options = {}, &block) concat(content_tag('div', capture(&block) + tag('br', :style => 'clear: left;'), { :class => 'button-bar' }.merge(options)), block.binding) end def partial_for_class(klass) if klass.nil? raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' end name = klass.name.underscore if File.exists?(File.join(RAILS_ROOT, 'app', 'views', params[:controller], "_#{name}.rhtml")) name else partial_for_class(klass.superclass) end end def partial_for_task_class(klass, action) if klass.nil? raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' end name = "#{klass.name.underscore}_#{action.to_s}" if File.exists?(File.join(RAILS_ROOT, 'app', 'views', params[:controller], "_#{name}.rhtml")) name else partial_for_task_class(klass.superclass, action) end end def user @controller.send(:user) end # DEPRECATED. Do not use this. def stylesheet_import(*sources) options = sources.last.is_a?(Hash) ? sources.pop : { } themed_source = options.delete(:themed_source) content_tag( 'style', "\n" + sources.flatten.map do |source| filename = filename_for_stylesheet(source.to_s, themed_source) if File.exists?(File.join(RAILS_ROOT, 'public', filename)) "@import url(#{filename});\n" else "/* Not included: url(#{filename}) */\n" end end.join(), { "type" => "text/css" }.merge(options) ) end # DEPRECATED. Do not use this. def filename_for_stylesheet(name, in_theme) result = '' if in_theme result << theme_path end name += '.css' if ( name[-4..-1] != '.css' ) if ( name[0..0] == '/' ) result << name else result << '/stylesheets/' << name end end def theme_path if session[:theme] '/user_themes/' + current_theme else '/designs/themes/' + current_theme end end def theme_stylesheet_path theme_path + '/style.css' end def current_theme @current_theme ||= begin if (session[:theme]) session[:theme] else # utility for developers: set the theme to 'random' in development mode and # you will get a different theme every request. This is interesting for # testing if ENV['RAILS_ENV'] == 'development' && environment.theme == 'random' @random_theme ||= Dir.glob('public/designs/themes/*').map { |f| File.basename(f) }.rand @random_theme elsif ENV['RAILS_ENV'] == 'development' && params[:theme] && File.exists?(File.join(Rails.root, 'public/designs/themes', params[:theme])) params[:theme] else if profile && !profile.theme.nil? profile.theme elsif environment environment.theme else if logger logger.warn("No environment found. This is weird.") logger.warn("Request environment: %s" % request.env.inspect) logger.warn("Request parameters: %s" % params.inspect) end # could not determine the theme, so return the default one 'default' end end end end end def theme_include(template) ['.rhtml', '.html.erb'].each do |ext| file = (RAILS_ROOT + '/public' + theme_path + '/' + template + ext) if File.exists?(file) return render :file => file, :use_full_path => false end end nil end def theme_favicon return '/designs/themes/' + current_theme + '/favicon.ico' if profile.nil? || profile.theme.nil? if File.exists?(File.join(RAILS_ROOT, 'public', theme_path, 'favicon.ico')) '/designs/themes/' + profile.theme + '/favicon.ico' else favicon = profile.articles.find_by_path('favicon.ico') if favicon favicon.public_filename else '/designs/themes/' + environment.theme + '/favicon.ico' end end end def theme_site_title theme_include('site_title') end def theme_header theme_include('header') end def theme_footer theme_include('footer') end def theme_extra_navigation theme_include('navigation') end def is_testing_theme !@controller.session[:theme].nil? end def theme_owner Theme.find(current_theme).owner.identifier end # generates a image tag for the profile. # # If the profile has no image set yet, then a default image is used. def profile_image(profile, size=:portrait, opt={}) return '' if profile.nil? opt[:alt] ||= profile.name() opt[:title] ||= '' opt[:class] ||= '' opt[:class] += ( profile.class == Person ? ' photo' : ' logo' ) image_tag(profile_icon(profile, size), opt ) end def profile_icon( profile, size=:portrait, return_mimetype=false ) filename, mimetype = '', 'image/png' if profile.image filename = profile.image.public_filename( size ) mimetype = profile.image.content_type else icon = if profile.organization? if profile.kind_of?(Community) '/images/icons-app/community-'+ size.to_s() +'.png' else '/images/icons-app/enterprise-'+ size.to_s() +'.png' end else '/images/icons-app/person-'+ size.to_s() +'.png' end filename = default_or_themed_icon(icon) end return_mimetype ? [filename, mimetype] : filename end def default_or_themed_icon(icon) if File.exists?(File.join(Rails.root, 'public', theme_path, icon)) theme_path + icon else icon end end def profile_sex_icon( profile ) return '' unless profile.is_a?(Person) return '' unless !environment.enabled?('disable_gender_icon') sex = ( profile.sex ? profile.sex.to_s() : 'undef' ) title = ( sex == 'undef' ? _('non registered gender') : ( sex == 'male' ? _('Male') : _('Female') ) ) sex = content_tag 'span', content_tag( 'span', sex ), :class => 'sex-'+sex, :title => title sex end def profile_cat_icons( profile ) if profile.class == Enterprise icons = profile.product_categories.map{ |c| c.size > 1 ? c[1] : nil }. compact.uniq.map{ |c| cat_name = c.gsub( /[-_\s,.;'"]+/, '_' ) cat_icon = "/images/icons-cat/#{cat_name}.png" if ! File.exists? RAILS_ROOT.to_s() + '/public/' + cat_icon cat_icon = '/images/icons-cat/undefined.png' end content_tag 'span', content_tag( 'span', c ), :title => c, :class => 'product-cat-icon cat_icon_' + cat_name, :style => "background-image:url(#{cat_icon})" }.join "\n" content_tag 'div', content_tag( 'span', _('Principal Product Categories'), :class => 'header' ) +"\n"+ icons, :class => 'product-category-icons' else '' end end def links_for_balloon(profile) if environment.enabled?(:show_balloon_with_profile_links_when_clicked) if profile.kind_of?(Person) [ {_('Wall') => {:href => url_for(profile.public_profile_url)}}, {_('Friends') => {:href => url_for(:controller => :profile, :action => :friends, :profile => profile.identifier)}}, {_('Communities') => {:href => url_for(:controller => :profile, :action => :communities, :profile => profile.identifier)}}, {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email', :style => 'display: none'}}, {_('Add') => {:href => url_for(profile.add_url), :class => 'add-friend', :style => 'display: none'}} ] elsif profile.kind_of?(Community) [ {_('Wall') => {:href => url_for(profile.public_profile_url)}}, {_('Members') => {:href => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)}}, {_('Agenda') => {:href => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)}}, {_('Join') => {:href => url_for(profile.join_url), :class => 'join-community', :style => 'display: none'}}, {_('Leave') => {:href => url_for(profile.leave_url), :class => 'leave-community', :style => 'display: none'}}, {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email', :style => 'display: none'}} ] elsif profile.kind_of?(Enterprise) [ {_('Products') => {:href => catalog_path(profile.identifier)}}, {_('Members') => {:href => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)}}, {_('Agenda') => {:href => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)}}, {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email', :style => 'display: none'}}, ] else [] end end end # displays a link to the profile homepage with its image (as generated by # #profile_image) and its name below it. def profile_image_link( profile, size=:portrait, tag='li', extra_info = nil ) name = profile.short_name if profile.person? url = url_for(profile.check_friendship_url) trigger_class = 'person-trigger' else city = '' url = url_for(profile.check_membership_url) if profile.community? trigger_class = 'community-trigger' elsif profile.enterprise? trigger_class = 'enterprise-trigger' end end extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' ) links = links_for_balloon(profile) content_tag tag, (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => "menu-submenu-trigger #{trigger_class}", :url => url) : "") + link_to( content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) + extra_info + profile_sex_icon( profile ) + profile_cat_icons( profile ), profile.url, :class => 'profile_link url', :help => _('Click on this icon to go to the %s\'s home page') % profile.name, :title => profile.name ), :class => 'vcard' end def gravatar_url_for(email, options = {}) # Ta dando erro de roteamento url_for( { :gravatar_id => Digest::MD5.hexdigest(email), :host => 'www.gravatar.com', :protocol => 'http://', :only_path => false, :controller => 'avatar.php', :d => NOOSFERO_CONF['gravatar'] ? NOOSFERO_CONF['gravatar'] : nil }.merge(options) ) end def str_gravatar_url_for(email, options = {}) default = NOOSFERO_CONF['gravatar'] ? NOOSFERO_CONF['gravatar'] : nil url = 'http://www.gravatar.com/avatar.php?gravatar_id=' + Digest::MD5.hexdigest(email) { :only_path => false, :d => default }.merge(options).each { |k,v| url += ( '&%s=%s' % [ k,v ] ) } url end attr_reader :environment def select_categories(object_name, title=nil, title_size=4) return nil if environment.enabled?(:disable_categories) if title.nil? title = _('Categories') end object = instance_variable_get("@#{object_name}") result = content_tag 'h'+title_size.to_s(), title result << javascript_tag( 'function open_close_cat( link ) { var div = link.parentNode.getElementsByTagName("div")[0]; var end = function(){ if ( div.style.display == "none" ) { this.link.className="button icon-button icon-down" } else { this.link.className="button icon-button icon-up-red" } } Effect.toggle( div, "slide", { link:link, div:div, afterFinish:end } ) }') environment.top_level_categories.select{|i| !i.children.empty?}.each do |toplevel| next unless object.accept_category?(toplevel) # FIXME ([toplevel] + toplevel.children_for_menu).each do |cat| if cat.top_level? result << '
' result << icon_button( :down, _('open'), '#', :onclick => 'open_close_cat(this); return false' ) result << content_tag('h5', toplevel.name) result << '
' end content_tag('div', result) end def select_folder(label, object, method, collection, html_options = {}, js_options = {}) root = profile ? profile.identifier : _("root") labelled_form_field(label, select(object, method, collection.map {|f| [ root + '/' + f.full_name, f.id ]}, {:include_blank => root}, html_options.merge(js_options))) end def select_profile_folder(label, object, method, profile, html_options = {}, js_options = {}) labelled_form_field(label, select(object, method, profile.folders.map {|f| [ profile.identifier + '/' + f.full_name, f.id ]}, {:include_blank => profile.identifier}, html_options.merge(js_options))) end def theme_option(opt = nil) conf = RAILS_ROOT.to_s() + '/public' + theme_path + '/theme.yml' if File.exists?(conf) opt ? YAML.load_file(conf)[opt.to_s()] : YAML.load_file(conf) else nil end end def theme_opt_menu_search opt = theme_option( :menu_search ) if opt == 'none' "" elsif opt == 'simple_search' s = _('Search...') "
'search', :action => 'index')}\" id=\"simple-search\" class=\"focus-out\""+ ' help="'+_('This is a search box. Click, write your query, and press enter to find')+'"'+ ' title="'+_('Click, write and press enter to find')+'">'+ ''+ '
' else #opt == 'lightbox_link' is default lightbox_link_to ''+ _('Search'), { :controller => 'search', :action => 'popup', :category_path => (@category ? @category.explode_path : []) }, :id => 'open_search' end end def theme_javascript option = theme_option(:js) return if option.nil? html = [] option.each do |file| file = theme_path + '/javascript/'+ file +'.js' if File.exists? RAILS_ROOT.to_s() +'/public'+ file html << javascript_src_tag( file, {} ) else html << '' end end html.join "\n" end def theme_javascript_ng script = File.join(theme_path, 'theme.js') if File.exists?(File.join(Rails.root, 'public', script)) javascript_include_tag script else nil end end def file_field_or_thumbnail(label, image, i) display_form_field label, ( render :partial => (image && image.valid? ? 'shared/show_thumbnail' : 'shared/change_image'), :locals => { :i => i, :image => image } ) end def rolename_for(profile, resource) role = profile.role_assignments.find_by_resource_id(resource.id).role content_tag('span', role.name, :style => "color: #{role_color(role, resource.environment.id)}") end def role_color(role, env_id) case role when Profile::Roles.admin(env_id) 'blue' when Profile::Roles.member(env_id) 'green' when Profile::Roles.moderator(env_id) 'gray' else 'black' end end # Should be on the forms_helper file but when its there the translation of labels doesn't work class NoosferoFormBuilder < ActionView::Helpers::FormBuilder extend ActionView::Helpers::TagHelper def self.output_field(text, field_html, field_id = nil) # try to guess an id if none given if field_id.nil? field_html =~ /id=['"]([^'"]*)['"]/ field_id = $1 end field_html =~ /type=['"]([^'"]*)['"]/ field_html =~ /<(\w*)/ unless $1 field_type = $1 field_class = 'formfield type-' + field_type if field_type label_html = content_tag('label', gettext(text), :class => 'formlabel', :for => field_id) control_html = content_tag('div', field_html, :class => field_class ) content_tag('div', label_html + control_html, :class => 'formfieldline' ) end (field_helpers - %w(hidden_field)).each do |selector| src = <<-END_SRC def #{selector}(field, *args, &proc) text = object.class.human_attribute_name(field.to_s) NoosferoFormBuilder::output_field(text, super) end END_SRC class_eval src, __FILE__, __LINE__ end # Create a formatable radio collection # Tha values parameter is a array of [value, label] arrays like this: # [ ['en',_('English')], ['pt',_('Portuguese')], ['es',_('Spanish')] ] # The option :size will set how many radios will be showed in each line # Example: use :size => 3 as option if you want 3 radios by line def radio_group( object_name, method, values, options = {} ) line_size = options[:size] || 0 line_item = 0 html = "\n" values.each { |val, h_val| id = object_name.to_s() +'_'+ method.to_s() +'_'+ val.to_s() # Não está apresentando o sexo selecionado ao revisitar # http://localhost:3000/myprofile/manuel/profile_editor/edit :-( html += self.class.content_tag( 'span', @template.radio_button( object_name, method, val, :id => id, :object => @object ) + self.class.content_tag( 'label', h_val, :for => id ), :class => 'lineitem' + (line_item+=1).to_s() ) +"\n" if line_item == line_size line_item = 0 html += "
\n" end } html += "
\n" if line_size == 0 || ( values.size % line_size ) > 0 column = object.class.columns_hash[method.to_s] text = ( column ? column.human_name : _(method.to_s.humanize) ) label_html = self.class.content_tag 'label', text, :class => 'formlabel' control_html = self.class.content_tag 'div', html, :class => 'formfield type-radio '+ 'fieldgroup linesize'+line_size.to_s() self.class.content_tag 'div', label_html + control_html, :class => 'formfieldline' end end # create a form field structure (as if it were generated with # labelled_form_for), but with a customized control and label. # # If +field_id+ is not given, the underlying implementation will try to guess # it from +field_html+ using a regular expression. In this case, make sure # that the first ocurrance of id=['"]([^'"]*)['"] in +field_html+ if the one # you want (i.e. the correct id for the control ) def labelled_form_field(label, field_html, field_id = nil) NoosferoFormBuilder::output_field(label, field_html, field_id) end alias_method :display_form_field, :labelled_form_field def labelled_fields_for(name, object = nil, options = {}, &proc) object ||= instance_variable_get("@#{name}") fields_for(name, object, { :builder => NoosferoFormBuilder }.merge(options), &proc) end def labelled_form_for(name, object = nil, options = {}, &proc) object ||= instance_variable_get("@#{name}") form_for(name, object, { :builder => NoosferoFormBuilder }.merge(options), &proc) end def optional_field(profile, name, field_html = nil, only_required = false, &block) result = "" is_required = false if profile.required_fields.include?(name) is_required = true else return result if only_required end if block field_html ||= '' field_html += capture(&block) end if controller.action_name == 'signup' || controller.action_name == 'new_community' || (controller.controller_name == "enterprise_registration" && controller.action_name == 'index') if profile.signup_fields.include?(name) result = field_html end else if profile.active_fields.include?(name) result = field_html end end if is_required result = required(result) end if block concat(result, block.binding) end result end def search_page_title(title, options={}) title = "

" + title + "

" title += "

" + _("Searched for '%s'") % options[:query] + "

" if !options[:query].blank? title += "

" + _("In category %s") % options[:category] + "

" if !options[:category].blank? title += "

" + _("within %d km from %s") % [options[:distance], options[:region]] + "

" if !options[:distance].blank? && !options[:region].blank? title += "

" + _("%d results found") % options[:total_results] + "

" if !options[:total_results].blank? title end def search_page_link_to_all(options={}) if options[:category] title = "
" + _('In all categories') + "
" link_to title, :action => 'assets', :asset => options[:asset], :category_path => [] end end def template_stylesheet_path if profile.nil? '/designs/templates/default/stylesheets/style.css' else "/designs/templates/#{profile.layout_template}/stylesheets/style.css" end end def login_url options = Noosfero.url_options.merge({ :controller => 'account', :action => 'login' }) if environment.enable_ssl && (ENV['RAILS_ENV'] != 'development') options.merge!(:protocol => 'https://', :host => ssl_hostname) end url_for(options) end def ssl_hostname environment.default_hostname end def base_url environment.top_url(request.ssl?) end def helper_for_article(article) article_helper = ActionView::Base.new article_helper.controller = controller article_helper.extend ArticleHelper begin class_name = article.class.name + 'Helper' klass = class_name.constantize article_helper.extend klass rescue end article_helper end def label_for_new_article(article) article_helper = helper_for_article(!article.nil? && !article.parent.nil? ? article.parent : article) article_helper.cms_label_for_new_children end def label_for_edit_article(article) article_helper = helper_for_article(article) article_helper.cms_label_for_edit end def add_rss_feed_to_head(title, url) content_for :feeds do tag(:link, :rel => 'alternate', :type => 'application/rss+xml', :title => title, :href => url_for(url)) end end def icon_theme_stylesheet_path icon_themes = [] theme_icon_themes = theme_option(:icon_theme) || [] for icon_theme in theme_icon_themes do theme_path = "/designs/icons/#{icon_theme}/style.css" if File.exists?(File.join(RAILS_ROOT, 'public', theme_path)) icon_themes << theme_path end end icon_themes end def page_title (@page ? @page.title + ' - ' : '') + (profile ? profile.short_name + ' - ' : '') + (@topic ? @topic.title + ' - ' : '') + (@section ? @section.title + ' - ' : '') + (@toc ? _('Online Manual') + ' - ' : '') + (@controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') + environment.name + (@category ? " - #{@category.full_name}" : '') end def noosfero_javascript render :file => 'layouts/_javascript' end def noosfero_stylesheets [ 'application', 'thickbox', 'lightbox', 'colorpicker', pngfix_stylesheet_path, ] end # DEPRECATED. Do not use this· def import_controller_stylesheets(options = {}) stylesheet_import( "controller_"+ @controller.controller_name(), options ) end def pngfix_stylesheet_path 'iepngfix/iepngfix.css' end def noosfero_layout_features render :file => 'shared/noosfero_layout_features' end def link_to_email(email) javascript_tag('var array = ' + email.split('@').to_json + '; document.write("" + array.join("@") + "")') end def stylesheet(*args) content_for(:head) { stylesheet_link_tag(*args) } end def article_to_html(article, options = {}) options.merge!(:page => params[:npage]) content = article.to_html(options) content = content.kind_of?(Proc) ? self.instance_eval(&content) : content @plugins && @plugins.enabled_plugins.each do |plugin| content = plugin.parse_content(content) end content end def colorpicker_field(object_name, method, options = {}) text_field(object_name, method, options.merge(:class => 'colorpicker_field')) end def colorpicker_field_tag(name, value = nil, options = {}) text_field_tag(name, value, options.merge(:class => 'colorpicker_field')) end def ui_icon(icon_class, extra_class = '') "" end def ui_button(label, url, html_options = {}) link_to(label, url, html_options.merge(:class => 'ui_button fg-button')) end def ui_button_to_remote(label, options, html_options = {}) link_to_remote(label, options, html_options.merge(:class => 'ui_button fg-button')) end def jquery_theme theme_option(:jquery_theme) || 'smoothness_mod' end def jquery_ui_theme_stylesheet_path 'jquery.ui/' + jquery_theme + '/jquery-ui-1.8.2.custom' end def ui_error(message) content_tag('div', ui_icon('ui-icon-alert') + message, :class => 'alert fg-state-error ui-state-error') end def ui_highlight(message) content_tag('div', ui_icon('ui-icon-info') + message, :class => 'alert fg-state-highlight ui-state-highlight') end def float_to_currency(value) number_to_currency(value, :unit => environment.currency_unit, :separator => environment.currency_separator, :delimiter => environment.currency_delimiter, :format => "%u %n") end def collapsed_item_icon "" end def expanded_item_icon "" end def leaf_item_icon "" end def display_category_menu(block, categories, root = true) categories = categories.sort{|x,y| x.name <=> y.name} return "" if categories.blank? content_tag(:ul, categories.map do |category| category_path = category.kind_of?(ProductCategory) ? {:controller => 'search', :action => 'assets', :asset => 'products', :product_category => category.id} : { :controller => 'search', :action => 'category_index', :category_path => category.explode_path } category.display_in_menu? ? content_tag(:li, ( !category.is_leaf_displayable_in_menu? ? content_tag(:a, collapsed_item_icon, :href => "#", :id => "block_#{block.id}_category_#{category.id}", :class => 'category-link-expand ' + (root ? 'category-root' : 'category-no-root'), :onclick => "expandCategory(#{block.id}, #{category.id}); return false", :style => 'display: none') : leaf_item_icon) + link_to(content_tag(:span, category.name, :class => 'category-name'), category_path, :class => ("category-leaf" if category.is_leaf_displayable_in_menu?)) + content_tag(:div, display_category_menu(block, category.children, false), :id => "block_#{block.id}_category_content_#{category.id}", :class => 'child-category') ) : '' end ) + content_tag(:p) + (root ? javascript_tag(" jQuery('.child-category').hide(); jQuery('.category-link-expand').show(); var expanded_icon = \"#{ expanded_item_icon }\"; var collapsed_icon = \"#{ collapsed_item_icon }\"; var category_expanded = { 'block' : 0, 'category' : 0 }; ") : '') end def browse_people_menu links = [ {s_('people|More Recent') => {:href => url_for({:controller => 'browse', :action => 'people', :filter => 'more_recent'})}}, {s_('people|More Active') => {:href => url_for({:controller => 'browse', :action => 'people', :filter => 'more_active'})}}, {s_('people|More Popular') => {:href => url_for({:controller => 'browse', :action => 'people', :filter => 'more_popular'})}} ] if logged_in? links.push(_('My friends') => {:href => url_for({:profile => current_user.login, :controller => 'friends'})}) links.push(_('Invite friends') => {:href => url_for({:profile => current_user.login, :controller => 'invite', :action => 'friends'})}) end link_to(content_tag(:span, _('People'), :class => 'icon-menu-people'), {:controller => "browse", :action => 'people'}, :id => 'submenu-people') + link_to(content_tag(:span, _('People Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-people-trigger') end def browse_communities_menu links = [ {s_('communities|More Recent') => {:href => url_for({:controller => 'browse', :action => 'communities', :filter => 'more_recent'})}}, {s_('communities|More Active') => {:href => url_for({:controller => 'browse', :action => 'communities', :filter => 'more_active'})}}, {s_('communities|More Popular') => {:href => url_for({:controller => 'browse', :action => 'communities', :filter => 'more_popular'})}} ] if logged_in? links.push(_('My communities') => {:href => url_for({:profile => current_user.login, :controller => 'memberships'})}) links.push(_('New community') => {:href => url_for({:profile => current_user.login, :controller => 'memberships', :action => 'new_community'})}) end link_to(content_tag(:span, _('Communities'), :class => 'icon-menu-community'), {:controller => "browse", :action => 'communities'}, :id => 'submenu-communities') + link_to(content_tag(:span, _('Communities Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-communities-trigger') end def pagination_links(collection, options={}) options = {:prev_label => '« ' + _('Previous'), :next_label => _('Next') + ' »'}.merge(options) will_paginate(collection, options) end def render_environment_features(folder) result = '' environment.enabled_features.keys.each do |feature| file = File.join(@controller.view_paths, 'shared', folder.to_s, "#{feature}.rhtml") if File.exists?(file) result << render(:file => file, :use_full_path => false) end end result end def manage_enterprises if user && !user.enterprises.empty? enterprises_link = user.enterprises.map do |enterprise| link_to(content_tag('strong', [_('Manage %s') % enterprise.short_name(25)]), @environment.top_url + "/myprofile/#{enterprise.identifier}", :class => "icon-menu-enterprise", :title => [_('Manage %s') % enterprise.short_name]) end render :partial => 'shared/manage_enterprises', :locals => {:enterprises_link => enterprises_link} end end def usermenu_logged_in pending_tasks_count = '' if user && user.all_pending_tasks.count > 0 pending_tasks_count = link_to(user.all_pending_tasks.count.to_s, @environment.top_url + '/myprofile/{login}/tasks', :id => 'pending-tasks-count', :title => _("Manage your pending tasks")) end (_('Welcome, %s') % link_to('{login}', @environment.top_url + '/{login}', :id => "homepage-link", :title => _('Go to your homepage'))) + render_environment_features(:usermenu) + link_to('' + _('Administration') + '', @environment.top_url + '/admin', :id => "controlpanel", :title => _("Configure the environment"), :class => 'admin-link', :style => 'display: none') + manage_enterprises.to_s + link_to('' + _('Control panel') + '', @environment.top_url + '/myprofile/{login}', :id => "controlpanel", :title => _("Configure your personal account and content")) + pending_tasks_count + link_to('' + _('Logout') + '', { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system")) end def limited_text_area(object_name, method, limit, text_area_id, options = {}) content_tag(:div, [ text_area(object_name, method, { :id => text_area_id, :onkeyup => "limited_text_area('#{text_area_id}', #{limit})" }.merge(options)), content_tag(:p, content_tag(:span, limit) + ' ' + _(' characters left'), :id => text_area_id + '_left'), content_tag(:p, _('Limit of characters reached'), :id => text_area_id + '_limit', :style => 'display: none') ], :class => 'limited-text-area') end def pluralize_without_count(count, singular, plural = nil) count == 1 ? singular : (plural || singular.pluralize) end def unique_with_count(list, connector = 'for') list.sort.inject(Hash.new(0)){|h,i| h[i] += 1; h }.collect{ |x, n| [n, connector, x].join(" ") }.sort end #FIXME Use time_ago_in_words instead of this method if you're using Rails 2.2+ def time_ago_as_sentence(from_time, include_seconds = false) to_time = Time.now from_time = from_time.to_time if from_time.respond_to?(:to_time) to_time = to_time.to_time if to_time.respond_to?(:to_time) distance_in_minutes = (((to_time - from_time).abs)/60).round distance_in_seconds = ((to_time - from_time).abs).round case distance_in_minutes when 0..1 return (distance_in_minutes == 0) ? _('less than a minute') : _('1 minute') unless include_seconds case distance_in_seconds when 0..4 then _('less than 5 seconds') when 5..9 then _('less than 10 seconds') when 10..19 then _('less than 20 seconds') when 20..39 then _('half a minute') when 40..59 then _('less than a minute') else _('1 minute') end when 2..44 then _('%{distance} minutes') % { :distance => distance_in_minutes } when 45..89 then _('about 1 hour') when 90..1439 then _('about %{distance} hours') % { :distance => (distance_in_minutes.to_f / 60.0).round } when 1440..2879 then _('1 day') when 2880..43199 then _('%{distance} days') % { :distance => (distance_in_minutes / 1440).round } when 43200..86399 then _('about 1 month') when 86400..525599 then _('%{distance} months') % { :distance => (distance_in_minutes / 43200).round } when 525600..1051199 then _('about 1 year') else _('over %{distance} years') % { :distance => (distance_in_minutes / 525600).round } end end def comment_balloon(options = {}, &block) wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content') (1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") } classes = options.delete(:class) || options.delete("class") || '' concat(content_tag('div', wrapper + tag('br', :style => 'clear: both;'), { :class => 'comment-balloon ' + classes.to_s }.merge(options)), block.binding) end def display_source_info(page) if !page.source.blank? source_url = link_to(page.source_name.blank? ? page.source : page.source_name, page.source) elsif page.reference_article source_url = link_to(page.reference_article.profile.name, page.reference_article.url) end content_tag(:div, _('Source: %s') % source_url, :id => 'article-source') unless source_url.nil? end def task_information(task) values = {} values.merge!({:requestor => link_to(task.requestor.name, task.requestor.public_profile_url)}) if task.requestor values.merge!({:subject => content_tag('span', task.subject, :class=>'task_target')}) if task.subject values.merge!({:linked_subject => link_to(content_tag('span', task.linked_subject[:text], :class => 'task_target'), task.linked_subject[:url])}) if task.linked_subject values.merge!(task.information[:variables]) if task.information[:variables] task.information[:message] % values end def add_zoom_to_images if environment.enabled?(:show_zoom_button_on_article_images) stylesheet_link_tag('fancybox') + javascript_include_tag('jquery.fancybox-1.3.4.pack') + javascript_tag("jQuery(function($) { $(window).load( function() { $('#article .article-body img').each( function(index) { var original = original_image_dimensions($(this).attr('src')); if ($(this).width() < original['width'] || $(this).height() < original['height']) { $(this).wrap('
'); $(this).parent('.zoomable-image').attr('style', $(this).attr('style')); $(this).attr('style', ''); $(this).after(\'%s'); } }); $('.zoomify-image').fancybox(); }); });" % _('Zoom in')) end end def render_dialog_error_messages(instance_name) render :partial => 'shared/dialog_error_messages', :locals => { :object_name => instance_name } end end