Module: ApplicationHelper

Defined in:
app/helpers/application_helper.rb

Overview

Fat Free CRM Copyright © 2008-2011 by Michael Dvorkin

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see <www.gnu.org/licenses/>.


Instance Method Summary collapse

Instance Method Details

#address_field(form, object, attribute, extra_styles) ⇒ Object

Render a text field that is part of compound address.




355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# File 'app/helpers/application_helper.rb', line 355

def address_field(form, object, attribute, extra_styles)
  hint = "#{t(attribute)}..."
  if object.send(attribute).blank?
    object.send("#{attribute}=", hint)
    form.text_field(attribute,
      :hint    => true,
      :style   => "margin-top: 6px; color:silver; #{extra_styles}",
      :onfocus => "crm.hide_hint(this)",
      :onblur  => "crm.show_hint(this, '#{hint}')"
    )
  else
    form.text_field(attribute,
      :hint    => false,
      :style   => "margin-top: 6px; #{extra_styles}",
      :onfocus => "crm.hide_hint(this, '#{escape_javascript(object.send(attribute))}')",
      :onblur  => "crm.show_hint(this, '#{hint}')"
    )
  end
end

#arrow_for(id) ⇒ Object




107
108
109
# File 'app/helpers/application_helper.rb', line 107

def arrow_for(id)
  (:span, "&#9658;".html_safe, :id => "#{id}_arrow", :class => :arrow)
end

#autocomplete_text_field(id, values) ⇒ Object

Adds autocomplete functionality to an existing text field.




428
429
430
431
432
433
# File 'app/helpers/application_helper.rb', line 428

def autocomplete_text_field(id, values)
  javascript_tag %Q{
    var textField = jQuery('##{id}');
    textField.autocomplete({ source: #{values} });
  }
end

#avatar_for(model, args = {}) ⇒ Object

Users can upload their avatar, and if it’s missing we’re going to use gravatar. For leads and contacts we always use gravatars.




305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'app/helpers/application_helper.rb', line 305

def avatar_for(model, args = {})
  args = { :class => 'gravatar', :size => :large }.merge(args)
  if model.avatar
    Avatar
    image_tag(model.avatar.image.url(args[:size]), args)
  elsif model.email
    # Gravatar requires '75x75' format, so convert symbols keys (e.g. :large)
    if style_size = Avatar::STYLES[args[:size]]
      args[:size] = style_size.sub(/\#$/,'')
    end
    # If we are passing an explicit w*h override (for uploaded avatars),
    # then use that as the size.
    if args[:width] && args[:height]
      args[:size] = [:width, :height].map{|d|args[d]}.join("x")
    end
    gravatar_for(model, args)
  else
    image_tag("avatar.jpg", args)
  end
end

#confirm_delete(model, params = {}) ⇒ Object




212
213
214
215
216
217
218
219
220
# File 'app/helpers/application_helper.rb', line 212

def confirm_delete(model, params = {})
  question = %(<span class="warn">#{t(:confirm_delete, model.class.to_s.downcase)}</span>).html_safe
  yes = link_to(t(:yes_button), params[:url] || model, :method => :delete)
  no = link_to_function(t(:no_button), "$('menu').update($('confirm').innerHTML)")
  update_page do |page|
    page << "$('confirm').update($('menu').innerHTML)"
    page[:menu].replace_html "#{question} #{yes} : #{no}"
  end
end

#default_avatar_urlObject




334
335
336
337
338
339
340
341
# File 'app/helpers/application_helper.rb', line 334

def default_avatar_url
  url = image_path('avatar.jpg')
  if ActionController::Base.config.asset_host.present?
    url
  else
    request.protocol + request.host_with_port + url
  end
end

#exposedObject



192
# File 'app/helpers/application_helper.rb', line 192

def exposed;   { :style => "display:block;"      }; end

#get_browser_timezone_offsetObject

Ajax helper to pass browser timezone offset to the server.




284
285
286
287
288
289
290
291
# File 'app/helpers/application_helper.rb', line 284

def get_browser_timezone_offset
  unless session[:timezone_offset]
    remote_function(
      :url  => timezone_path,
      :with => "'offset='+(new Date()).getTimezoneOffset()"
    )
  end
end

#get_default_permissions_intro(access, text) ⇒ Object

Returns default permissions intro.




345
346
347
348
349
350
351
# File 'app/helpers/application_helper.rb', line 345

def get_default_permissions_intro(access, text)
  case access
    when "Private" then t(:permissions_intro_private, text)
    when "Public"  then t(:permissions_intro_public,  text)
    when "Shared"  then t(:permissions_intro_shared,  text)
  end
end

#gravatar_for(model, args = {}) ⇒ Object

Gravatar helper that adds default CSS class and image URL.




328
329
330
331
# File 'app/helpers/application_helper.rb', line 328

def gravatar_for(model, args = {})
  args = { :class => 'gravatar', :gravatar => { :default => default_avatar_url } }.merge(args)
  gravatar_image_tag(model.email, args)
end

#hiddenObject




191
# File 'app/helpers/application_helper.rb', line 191

def hidden;    { :style => "display:none;"       }; end

#hidden_if(you_ask) ⇒ Object




202
203
204
# File 'app/helpers/application_helper.rb', line 202

def hidden_if(you_ask)
  you_ask ? hidden : exposed
end

#invisibleObject



193
# File 'app/helpers/application_helper.rb', line 193

def invisible; { :style => "visibility:hidden;"  }; end

#invisible_if(you_ask) ⇒ Object




207
208
209
# File 'app/helpers/application_helper.rb', line 207

def invisible_if(you_ask)
  you_ask ? invisible : visible
end

#jumpbox(current) ⇒ Object




177
178
179
180
181
182
183
# File 'app/helpers/application_helper.rb', line 177

def jumpbox(current)
  tabs = [ :campaigns, :accounts, :leads, :contacts, :opportunities ]
  current = tabs.first unless tabs.include?(current)
  tabs.map do |tab|
    link_to_function(t("tab_#{tab}"), "crm.jumper('#{tab}')", :class => (tab == current ? 'selected' : ''))
  end.join(" | ").html_safe
end


414
415
416
417
418
419
420
# File 'app/helpers/application_helper.rb', line 414

def link_to_add_fields(name, f, type)
  new_object = f.object.send "build_#{type}"
  fields = f.send("#{type}_fields", new_object, :child_index => "new_#{type}") do |builder|
    render(type.to_s + "_fields", :f => builder)
  end
  link_to name, nil, :class => "add_fields", "data-field-type" => type, "data-content" => "#{fields}"
end



147
148
149
150
151
152
153
# File 'app/helpers/application_helper.rb', line 147

def link_to_cancel(url, params = {})
  url = params[:url] if params[:url]
  link_to(t(:cancel),
    url + "#{url.include?('?') ? '&' : '?'}cancel=true",
    :remote => true
  )
end



156
157
158
159
160
161
162
# File 'app/helpers/application_helper.rb', line 156

def link_to_close(url)
  link_to("x", url + "#{url.include?('?') ? '&' : '?'}cancel=true",
    :remote => true,
    :class => "close",
    :title => t(:close_form)
  )
end



122
123
124
125
126
127
128
129
130
# File 'app/helpers/application_helper.rb', line 122

def link_to_delete(model, params = {})
  name = (params[:klass_name] || model.class.name).underscore.downcase
  link_to(t(:delete) + "!",
    params[:url] || url_for(model),
    :method => :delete,
    :remote => true,
    :onclick => visual_effect(:highlight, dom_id(model), :startcolor => "#ffe4e1")
  )
end



133
134
135
136
137
138
139
140
141
142
143
144
# File 'app/helpers/application_helper.rb', line 133

def link_to_discard(model)
  name = model.class.name.downcase
  current_url = (request.xhr? ? request.referer : request.fullpath)
  parent, parent_id = current_url.scan(%r|/(\w+)/(\d+)|).flatten

  link_to(t(:discard),
    url_for(:controller => parent, :action => :discard, :id => parent_id, :attachment => model.class.name, :attachment_id => model.id),
    :method  => :post,
    :remote  => true,
    :onclick => visual_effect(:highlight, dom_id(model), :startcolor => "#ffe4e1")
  )
end



112
113
114
115
116
117
118
119
# File 'app/helpers/application_helper.rb', line 112

def link_to_edit(model, params = {})
  name = (params[:klass_name] || model.class.name).underscore.downcase
  link_to(t(:edit),
    params[:url] || send(:"edit_#{name}_path", model),
    :remote  => true,
    :onclick => "this.href = this.href.split('?')[0] + '?previous='+crm.find_form('edit_#{name}');"
  )
end

Bcc: to dropbox address if the dropbox has been set up.




166
167
168
169
170
171
172
173
174
# File 'app/helpers/application_helper.rb', line 166

def link_to_email(email, length = nil)
  name = (length ? truncate(email, :length => length) : email)
  if Setting.email_dropbox && Setting.email_dropbox[:address].present?
    mailto = "#{email}?bcc=#{Setting.email_dropbox[:address]}"
  else
    mailto = email
  end
  link_to(h(name), "mailto:#{mailto}", :title => email)
end



94
95
96
97
98
99
100
101
102
103
104
# File 'app/helpers/application_helper.rb', line 94

def link_to_inline(id, url, options = {})
  text = options[:text] || t(id, :default => id.to_s.titleize)
  text = (arrow_for(id) + text) unless options[:plain]
  related = (options[:related] ? "&related=#{options[:related]}" : '')

  link_to(text,
    url + "#{url.include?('?') ? '&' : '?'}cancel=false" + related,
    :remote => true,
    :onclick => "this.href = this.href.replace(/cancel=(true|false)/,'cancel='+ Element.visible('#{id}'));"
  )
end


422
423
424
# File 'app/helpers/application_helper.rb', line 422

def link_to_remove_fields(name, f)
  link_to image_tag('delete.png', :size => '16x16', :alt => name), nil, :class => "remove_fields"
end

Helper to display links to supported data export formats.




387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
# File 'app/helpers/application_helper.rb', line 387

def links_to_export
  token = @current_user.single_access_token
  path = if controller.controller_name == 'home'
    activities_path
  elsif controller.class.to_s.starts_with?("Admin::")
    send("admin_#{controller.controller_name}_path")
  else
    send("#{controller.controller_name}_path")
  end

  exports = %w(xls csv).map do |format|
    link_to(format.upcase, "#{path}.#{format}", :title => I18n.t(:"to_#{format}"))
  end

  feeds = %w(rss atom).map do |format|
    link_to(format.upcase, "#{path}.#{format}?authentication_credentials=#{token}", :title => I18n.t(:"to_#{format}"))
  end

  (exports + feeds).join(' | ')
end

#load_select_popups_for(related, *assets) ⇒ Object




74
75
76
77
78
79
80
81
82
# File 'app/helpers/application_helper.rb', line 74

def load_select_popups_for(related, *assets)
  js = assets.map do |asset|
    render(:partial => "shared/select_popup", :locals => { :related => related, :popup => asset })
  end.join

  content_for(:javascript_epilogue) do
    raw "document.observe('dom:loaded', function() { #{js} });"
  end
end

#localize_calendar_date_selectObject




294
295
296
297
298
299
300
# File 'app/helpers/application_helper.rb', line 294

def localize_calendar_date_select
  update_page_tag do |page|
    page.assign '_translations', { 'OK' => t('calendar_date_select.ok'), 'Now' => t('calendar_date_select.now'), 'Today' => t('calendar_date_select.today'), 'Clear' => t('calendar_date_select.clear') }
    page.assign 'Date.weekdays', t('date.abbr_day_names')
    page.assign 'Date.months', t('date.month_names')[1..-1]
  end
end

#one_submit_only(form) ⇒ Object




197
198
199
# File 'app/helpers/application_helper.rb', line 197

def one_submit_only(form)
  { :onsubmit => "$$('#'+this.id+' input[type=\"submit\"]')[0].disabled = true" }
end

#options_menu_item(option, key, url = nil) ⇒ Object




270
271
272
273
274
275
276
277
278
279
280
# File 'app/helpers/application_helper.rb', line 270

def options_menu_item(option, key, url = nil)
  name = t("option_#{key}")
  "{ name: \"#{name.titleize}\", on_select: function() {" +
  remote_function(
    :url       => url || send("redraw_#{controller.controller_name}_path"),
    :with      => "'#{option}=#{key}'",
    :condition => "$('#{option}').innerHTML != '#{name}'",
    :loading   => "$('#{option}').update('#{name}'); $('loading').show()",
    :complete  => "$('loading').hide()"
  ) + "}}"
end

#rating_select(name, options = {}) ⇒ Object

We need this because standard Rails [select] turns &#9733; into &amp;#9733;




86
87
88
89
90
91
# File 'app/helpers/application_helper.rb', line 86

def rating_select(name, options = {})
  stars = Hash[ (1..5).map { |star| [ star, "&#9733;" * star ] } ].sort
  options_for_select = %Q(<option value="0"#{options[:selected].to_i == 0 ? ' selected="selected"' : ''}>#{t :select_none}</option>)
  options_for_select << stars.map { |star| %(<option value="#{star.first}"#{options[:selected] == star.first ? ' selected="selected"' : ''}>#{star.last}</option>) }.join
  select_tag name, options_for_select.html_safe, options
end

#redraw(option, value, url = nil) ⇒ Object

Ajax helper to refresh current index page once the user selects an option.




256
257
258
259
260
261
262
263
264
265
266
267
# File 'app/helpers/application_helper.rb', line 256

def redraw(option, value, url = nil)
  if value.is_a?(Array)
    param, value = value.first, value.last
  end
  remote_function(
    :url       => url || send("redraw_#{controller.controller_name}_path"),
    :with      => "'#{option}=#{param || value}'",
    :condition => "$('#{option}').innerHTML != '#{value}'",
    :loading   => "$('#{option}').update('#{value}'); $('loading').show()",
    :complete  => "$('loading').hide()"
  )
end

#refresh_sidebar(action = nil, shake = nil) ⇒ Object

Reresh sidebar using the action view within the current controller.




229
230
231
# File 'app/helpers/application_helper.rb', line 229

def refresh_sidebar(action = nil, shake = nil)
  refresh_sidebar_for(controller.controller_name, action, shake)
end

#refresh_sidebar_for(view, action = nil, shake = nil) ⇒ Object

Refresh sidebar using the action view within an arbitrary controller.




235
236
237
238
239
240
# File 'app/helpers/application_helper.rb', line 235

def refresh_sidebar_for(view, action = nil, shake = nil)
  update_page do |page|
    page[:sidebar].replace_html :partial => "layouts/sidebar", :locals => { :view => view, :action => action }
    page[shake].visual_effect(:shake, :duration => 0.2, :distance => 3) if shake
  end
end

#section(related, assets) ⇒ Object




59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'app/helpers/application_helper.rb', line 59

def section(related, assets)
  asset = assets.to_s.singularize
  create_id  = "create_#{asset}"
  select_id  = "select_#{asset}"
  create_url = controller.send(:"new_#{asset}_path")

  html = tag(:br)
  html << (:div, link_to(t(select_id), "#", :id => select_id), :class => "subtitle_tools")
  html << (:div, "&nbsp;|&nbsp;".html_safe, :class => "subtitle_tools")
  html << (:div, link_to_inline(create_id, create_url, :related => dom_id(related), :text => t(create_id)), :class => "subtitle_tools")
  html << (:div, t(assets), :class => :subtitle, :id => "create_#{asset}_title")
  html << (:div, "", :class => :remote, :id => create_id, :style => "display:none;")
end

#show_flash(options = { :sticky => false }) ⇒ Object

Show existing flash or embed hidden paragraph ready for flash




38
39
40
41
42
43
44
45
46
# File 'app/helpers/application_helper.rb', line 38

def show_flash(options = { :sticky => false })
  [:error, :warning, :info, :notice].each do |type|
    if flash[type]
      html = (:p, h(flash[type]), :id => "flash")
      return html << (:script, "crm.flash('#{type}', #{options[:sticky]})", :type => "text/javascript")
    end
  end
  (:p, nil, :id => "flash", :style => "display:none;")
end

#shown_on_landing_page?Boolean

Return true if:

- it's an Ajax request made from the asset landing page (i.e. create opportunity
  from a contact landing page) OR
- we're actually showing asset landing page.

Returns:

  • (Boolean)


380
381
382
383
# File 'app/helpers/application_helper.rb', line 380

def shown_on_landing_page?
  !!((request.xhr? && request.referer =~ %r|/\w+/\d+|) ||
     (!request.xhr? && request.fullpath =~ %r|/\w+/\d+|))
end

#spacer(width = 10) ⇒ Object




223
224
225
# File 'app/helpers/application_helper.rb', line 223

def spacer(width = 10)
  image_tag "1x1.gif", :width => width, :height => 1, :alt => nil
end

#styles_for(*models) ⇒ Object




186
187
188
# File 'app/helpers/application_helper.rb', line 186

def styles_for(*models)
  render :partial => "shared/inline_styles", :locals => { :models => models }
end

#subtitle(id, hidden = true, text = id.to_s.split("_").last.capitalize) ⇒ Object




49
50
51
52
53
54
55
56
# File 'app/helpers/application_helper.rb', line 49

def subtitle(id, hidden = true, text = id.to_s.split("_").last.capitalize)
  ("div",
    link_to("<small>#{ hidden ? "&#9658;" : "&#9660;" }</small> #{text}".html_safe,
      url_for(:controller => :home, :action => :toggle, :id => id),
      :remote => true,
      :onclick => "crm.flip_subtitle(this)"
    ), :class => "subtitle")
end

#tabless_layout?Boolean


Returns:

  • (Boolean)


31
32
33
34
# File 'app/helpers/application_helper.rb', line 31

def tabless_layout?
  %w(authentications passwords).include?(controller.controller_name) ||
  ((controller.controller_name == "users") && (%w(create new).include?(controller.action_name)))
end

#tabs(tabs = nil) ⇒ Object



20
21
22
23
24
25
26
27
28
# File 'app/helpers/application_helper.rb', line 20

def tabs(tabs = nil)
  tabs ||= controller_path =~ /admin/ ? FatFreeCRM::Tabs.admin : FatFreeCRM::Tabs.main
  if tabs
    @current_tab ||= tabs.first[:text] # Select first tab by default.
    tabs.each { |tab| tab[:active] = (@current_tab == tab[:text] || @current_tab == tab[:url][:controller]) }
  else
    raise FatFreeCRM::MissingSettings, "Tab settings are missing, please run <b>rake ffcrm:setup</b> command."
  end
end

#template_fields(f, type) ⇒ Object



408
409
410
411
412
# File 'app/helpers/application_helper.rb', line 408

def template_fields(f, type)
  f.grouping_fields f.object.new_grouping, :object_name => "new_object_name", :child_index => "new_grouping" do |builder|
    render('grouping_fields', :f => builder)
  end
end

#visibleObject



194
# File 'app/helpers/application_helper.rb', line 194

def visible;   { :style => "visibility:visible;" }; end

#web_presence_icons(person) ⇒ Object

Display web presence mini-icons for Contact or Lead.




244
245
246
247
248
249
250
251
252
# File 'app/helpers/application_helper.rb', line 244

def web_presence_icons(person)
  [ :blog, :linkedin, :facebook, :twitter, :skype ].map do |site|
    url = person.send(site)
    unless url.blank?
      url = "http://" << url unless url.match(/^https?:\/\//)
      link_to(image_tag("#{site}.gif", :size => "15x15"), url, :"data-popup" => true, :title => t(:open_in_window, url))
    end
  end.compact.join("\n").html_safe
end