Subversion Repositories mildred

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

# Methods added to this helper will be available to all templates in the application.

require "RMagick"

module ApplicationHelper
  include Magick

  def title(text)
    content_for(:title, content_tag(:title, text + ": Mildred"))
  end
 
  def dequeue
    html = content_tag(:div, :id => "dequeue") do
      attributes = {
        :alt => "Working...",
        :id => "dequeue_indicator",
        :style => "display: none;",
      }
      image_tag("indicator.gif", attributes) +
        content_tag(:span, :id => "dequeue_text") {"Dequeue"}
    end
    options = {
      :accept => "de",
      :hoverclass => "hover_class",
      :onDrop => "QUEUE.Dequeue.bind(QUEUE)",
    }
    html << drop_receiving_element("dequeue", options)
  end
 
  def requests
    html = content_tag(:div, :id => "requests") do
      attributes = {
        :alt => "Working...",
        :id => "requests_indicator",
        :style => "display: none;",
      }
      image_tag("indicator.gif", attributes) +
        content_tag(:span, :id => "requests_text") {"Drag requests here."}
    end
    options = {
      :accept => "tr",
      :hoverclass => "hover_class",
      :onDrop => "QUEUE.Request.bind(QUEUE)",
    }
    html << drop_receiving_element("requests", options)
    html << content_tag(:div, :class => "xx-small") {"* indicates a request"}
  end
 
  def queue_history
    content_tag(:ul, :id => "history") do
      render :partial => "/shared/playlist_track_history",
             :collection => @playlist[:history]
    end
  end

  # TODO rename me?
  def limit_string(s, lim)
    return h(s) unless s.size >= lim
    # remove the last 3 chars to make room for the ellipsis
    h(s[0..(lim-3)]) + "&hellip;"
  end

  def classify_media(media)
    classes = {
      :cds => [],
      :internet => false,
    }
    media.each do |medium|
      case medium.medium
      when "CD3", "CD5": classes[:cds] << medium.format
      when "Internet": classes[:internet] = true
      end
    end
    classes
  end
 
  def build_media_text(classes)
    text = []
    if classes[:cds].size > 1
      text << "#{classes[:cds].size}&times;CD"
    elsif classes[:cds].size == 1
      text << classes[:cds].first
    end
    if classes[:internet]
      text << "Internet"
    end
    text
  end
 
  def album_format(album)
    classes = classify_media(album.media)
    text = build_media_text(classes)
    if text.empty?
      logger.debug("No media found of which to report the format")
      return "?"
    else
      return text.join(", ")
    end
  end
 
  def divide_objects(objects)
    half = (objects.size / 2.0).ceil
    left = objects.slice(0, half)
    right = objects.slice(half, objects.size - half)
    [left, right]
  end

  def format_last_played(time)
    now = Time.new
    if time.nil? || time == Time.at(0)
      return "?"
    elsif time >= now.midnight
      return "Today at #{time.strftime("%I:%M %p")}."
    elsif time >= now.yesterday.midnight
      return "Yesterday at #{time.strftime("%I:%M %p")}."
    elsif time >= now.last_month
      return time_ago_in_words(time).capitalize + " ago."
    else
      return "More than a month ago."
    end
  end

  # return the track time as a string in hour:min:sec formatting.
  def formatted_time(time)
    hours = minutes = seconds = 0
    hours = time / 1.hour
    time -= hours * 1.hour
    minutes = time / 1.minute
    time -= minutes * 1.minute
    seconds = time
    if hours > 0
      return sprintf("%d:%02d:%02d", hours, minutes, seconds)
    else
      return sprintf("%01d:%02d", minutes, seconds)
    end
  end

  # TODO refactor me to take an argument, instead of relying on an instance var?
  def get_title
    @title.nil? ? "Mildred" : "#{@title} - Mildred"
  end

  def logged_in?
    !session[:user_id].nil?
  end

  def current_user
    @controller.send(:current_user)
  end

  # TODO refactor me and playlist_track
  def playlist_track_queue_id(track, counter)
    classes = ["playlist_track_queue_li"]
    classes << "de" if logged_in?
    track_id = "li_#{track.id}-#{counter}"
    html = content_tag(:li, :id => track_id, :class => classes.join(" ")) do
      playlist_track(track)
    end
    if !current_user.has_perm?(:reorder) && current_user.has_perm?(:dequeue)
      options = {
        :constraint => "\"vertical\"",
        :ghosting => false,
        :handle => "\"cropped\"",
        :revert => true,
      }
      html << draggable_element("li_#{track.id}_#{counter}", options)
    end
    return html
  end
 
  # TODO refactor me and playlist_track_queue_id
  def playlist_track(track, now_playing=false)
    if track.nil?
      render :partial => "/mildred/playlist_track_nil"
      return
    end
    opts = []
    # debugger
    path = track_path(track)
    time = track.last_played
    time ||= Time.now
    if !@playlist[:queue].index(track).nil?
      np = @playlist[:now_playing]
      pl_size = @playlist[:queue].size
      np_lp = np ? np.last_played : Time.now
      time = np ? np_lp + np.time.to_f : np_lp + Track.average(:time)
      @playlist[:queue].each do |tr|
        break if tr == track
        time += tr.time.to_f
      end
      opts << " onclick=\"return check_for_drag_n_drop()\""
    end
    opts << " accesskey=\" \"" if track == @playlist[:now_playing]
    opts << " onmouseover=\"show_track_details(this)\""
    opts << " onmouseout=\"hide_track_details(this)\""

    render :partial => "/shared/playlist_track",
           :locals => {:track => track, :time => time,
                       :url => path, :opts => opts}
  end

  def rating_graph(rating)
    rating = sprintf("%0.1f", rating.to_f).to_f
    r = content_tag("span", "#{rating > 0 ? rating : "?"}/10") + " "
    r += image_tag("pixel-grey.png", :style => "width: #{rating*(MINI_GRAPH_WIDTH_EM/10.0)}em", :class => "graph left", :alt => "small graph")
    if rating < 10
      r += image_tag("pixel-white.png", :style => "width: #{MINI_GRAPH_WIDTH_EM - (rating*(MINI_GRAPH_WIDTH_EM/10))}em", :class => "graph right", :alt => "small graph")
    end
    r
  end

  def rank_graph(rank, count)
    r = content_tag("span", rank) + " "
    r += image_tag("pixel-grey.png", :style => "width: #{MINI_GRAPH_WIDTH_EM - (rank.to_i*(MINI_GRAPH_WIDTH_EM/count))}em", :class => "graph left")
    if rank.to_i > 1
      r += image_tag("pixel-white.png", :style => "width: #{rank.to_i*(MINI_GRAPH_WIDTH_EM/count)}em", :class => "graph right")
    end
    r
  end

  def histogram(size, count)
    grey_width = size * (HISTOGRAM_WIDTH_EM / count)
    white_width = HISTOGRAM_WIDTH_EM - grey_width
    r = image_tag("pixel-grey.png",
                  :style => "width: #{grey_width}em",
                  :class => "graph left")
    r << image_tag("pixel-white.png",
                   :style => "width: #{white_width}em",
                   :class => "graph right")
  end

  def smart_quote(text)
    "&ldquo;#{text}&rdquo;"
  end

  def album_thumb(album, opts={})
    if album.art.size.zero? # we're going to get the default image
      title = "No album art"
      alt = "No image available"
      path = "noimage.png"
    else
      title = h(album.title)
      alt = "Album art: #{title}"
      path = album.art[rand(album.art.size)].public_filename("t")
    end
    opts.reverse_merge!(:class => "thumb_img", :alt => alt, :title => title)
    image_tag(path, opts)
  end

  def artist_thumb(artist, opts={})
    if artist.art.size > 0
      title = h(artist.name)
      alt = "Artist image: #{title}"
      path = artist.art[rand(artist.art.size)].public_filename("t")
    # elsif artist.image_urls.size > 0
    #   title = h(artist.name)
    #   alt = "Artist image: #{title}"
    #   path = artist.image_urls[rand(artist.image_urls.size)]
    else
      title = "No artist art"
      alt = "No image available"
      path = "noimage.png"
    end
    opts.reverse_merge!(:class => "thumb_img", :alt => alt, :title => title)
    image_tag(path, opts)
  end
 
  def link_to_album(album, options=Hash.new)
    options = {:title => "Album: #{album.title}"}.merge(options)
    options = {:class => "album_title"}.merge(options)
    link_to(h(album.title), album_path(album), options)
  end

  def link_to_artist(artist, options=Hash.new)
    options = {:title => "Artist: #{artist.name}"}.merge(options)
    link_to(h(artist.name), artist_path(artist), options)
  end

  def link_to_mood(mood, options=Hash.new)
    options = {:title => "Mood: #{mood.name}"}.merge(options)
    link_to(h(mood.name), mood_path(mood), options)
  end

  def rating_slider(playlist, value)
    if value < playlist[:now_playing].rating.to_i
      classes = "current"
    elsif value == playlist[:now_playing].rating.to_i
      classes = "current last"
    else
      classes = ""
    end
    "<span onmouseover=\"slider_set(this, true)\" " <<
      "onmouseout=\"slider_set(this, false)\" " <<
      "class=\"#{classes}\" " <<
      "onclick=\"report_rating(this, #{playlist[:now_playing].id})\">" <<
      "&nbsp;\n&nbsp;\n</span>"
  end

  def google_image_search(*keywords)
    args = URI.escape("\"" + keywords.join("\" \"") + "\"")
    link_to("Google Image Search",
            "http://images.google.com/images?q=#{args}",
            {:target =>"new",})
  end

  def image_dimensions(path)
    i = Image.read(RAILS_ROOT + "/public/images/" + path).first
    "#{i.columns}x#{i.rows}"
  end

  # Takes an array of objects and returns a hash of the first occurrance of
  # each first letter from the objects's specified method.
  def generate_alpha_indices(objects, method)
    links = {}
    prev_letter = nil

    objects.each_with_index do |obj, index|
      first_letter = obj.send(method)[0..0].upcase
      unless /[A-Z]/ === first_letter
        first_letter = "#"
      end
      if first_letter != prev_letter
        links[first_letter] = index
        prev_letter = first_letter
      end
    end
   
    links
  end
 
  def plus_minus_toggle(id)
    link_to_function(content_tag(:span, "[-]", :id => id + "_toggler")) do |page|
      page[id].toggle
      page << "if (Element.visible('#{id}')) {$('#{id}_toggler').update('[-]')} else {$('#{id}_toggler').update('[+]')}"
    end
  end

  # note that this method is generally destructive, and not general-purpose
  def throbber(id, image)
    "$('#{id}').update('#{image_tag(image)}');"
  end
 
  def update_queue(page)
    page.replace_html(:playlist, :partial => "/shared/playlist")
    if current_user.has_perm?(:rate) && page["rating_block"]
      page.replace_html(:rating_block, :partial => "/shared/rating_slider")
    end
  end

  def handle_follow_mode(page)
    begin
      if session[:last_played_track_id] != @playlist[:now_playing].id
        session[:last_played_track_id] = @playlist[:now_playing].id
        page.redirect_to(track_path(@playlist[:now_playing]))
      end
    rescue
      logger.error("Error handling follow mode: #{$!}\n#{$!.backtrace.join("\n")}")
    end
  end
 
end