Skip to content

Commit

Permalink
Merge pull request #29 from claudiob/add-progress-bar
Browse files Browse the repository at this point in the history
Add progress_bar helper
  • Loading branch information
claudiofullscreen committed Sep 17, 2014
2 parents 7e66ad0 + 69ccfb0 commit 3b1ae16
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -11,6 +11,7 @@ For more information about changelogs, check
* [FEATURE] Add `icon` helper
* [FEATURE] Add `font_awesome_css` helper
* [FEATURE] Add `dropdown` helper
* [FEATURE] Add `progress_bar` helper

## 1.0.1 - 2014-09-14

Expand Down
66 changes: 66 additions & 0 deletions lib/bh/helpers/progress_bar_helper.rb
@@ -0,0 +1,66 @@
require 'bh/helpers/base_helper'

module Bh
# Provides methods to include progress bars.
# @see http://getbootstrap.com/components/#progress
module ProgressBarHelper
include BaseHelper

# Returns an HTML block tag that follows the Bootstrap documentation
# on how to display *progress bars*.
# @param [Hash, Array<Hash>] options the display options for the progress
# bar(s). When options is an Array, a group of stacked progress bars
# is displayed, with the options specified in each item of the array.
# @option options [Boolean, #to_s] :label (false) the label to display
# on top of the progress bar. If set to false, the label is hidden. If
# set to true, the label is generated from the percentage value. Any
# other provided value is used directly as the label.
# @option options [Boolean] :striped (false) whether to display a striped
# version of the progress bar (rather than solid color).
# @option options [Boolean] :animated (false) whether to display an
# animated version of the progress bar (rather than solid color).
# @option options [#to_s] :context (:default) the contextual alternative to
# apply to the progress bar depending on its importance. Can be
# `:success`, `:info`, `:warning` or `:danger`.
def progress_bar(options = {})
content_tag :div, class: :progress do
safe_join Array.wrap(options).map{|bar| progress_bar_string bar}, "\n"
end
end

private

def progress_bar_string(options = {})
percentage = options.fetch :percentage, 0

attributes = {}.tap do |attrs|
attrs[:class] = progress_bar_class(options)
attrs[:role] = 'progressbar'
attrs[:style] = "width: #{percentage}%"
attrs['aria-valuenow'] = percentage
attrs['aria-valuemin'] = 0
attrs['aria-valuemax'] = 100
end

content_tag :div, progress_bar_label(percentage, options), attributes
end

def progress_bar_label(percentage, options = {})
text = "#{percentage}%#{" (#{options[:context]})" if options[:context]}"
case options.fetch(:label, false)
when true then text
when false then content_tag(:span, text, class: 'sr-only')
else options[:label]
end
end

def progress_bar_class(options = {})
valid_contexts = %w(success info warning danger)
context = context_for options[:context], valid: valid_contexts
context = context.in?(valid_contexts) ? "progress-bar-#{context}" : nil
striped = 'progress-bar-striped' if options[:striped]
animated = 'progress-bar-striped active' if options[:animated]
['progress-bar', context, striped, animated].compact.join ' '
end
end
end
2 changes: 2 additions & 0 deletions lib/bh/middleman.rb
Expand Up @@ -11,6 +11,7 @@
require 'bh/helpers/navbar_helper'
require 'bh/helpers/panel_helper'
require 'bh/helpers/panel_row_helper'
require 'bh/helpers/progress_bar_helper'

module Bh
class MiddlemanExtension < Middleman::Extension
Expand All @@ -28,6 +29,7 @@ class MiddlemanExtension < Middleman::Extension
include NavbarHelper
include PanelHelper
include PanelRowHelper
include ProgressBarHelper
end
end
end
Expand Down
2 changes: 2 additions & 0 deletions lib/bh/railtie.rb
Expand Up @@ -11,6 +11,7 @@
require 'bh/helpers/navbar_helper'
require 'bh/helpers/panel_helper'
require 'bh/helpers/panel_row_helper'
require 'bh/helpers/progress_bar_helper'

module Bh
class Railtie < Rails::Railtie
Expand All @@ -28,6 +29,7 @@ class Railtie < Rails::Railtie
ActionView::Base.send :include, NavbarHelper
ActionView::Base.send :include, PanelHelper
ActionView::Base.send :include, PanelRowHelper
ActionView::Base.send :include, ProgressBarHelper
end

initializer 'bh.add_views' do |app|
Expand Down
114 changes: 114 additions & 0 deletions spec/helpers/progress_bar_helper_spec.rb
@@ -0,0 +1,114 @@
# encoding: UTF-8

require 'spec_helper'
require 'bh/helpers/progress_bar_helper'

include Bh::ProgressBarHelper

describe 'progress_bar' do
context 'without options' do
let(:html) { progress_bar }

it 'displays an empty progress bar' do
expect(html).to include '<div class="progress">'
end
end

context 'with a hash of options' do
let(:html) { progress_bar options.merge(percentage: 30) }
let(:options) { {} }

it 'displays one progress bar for the given value' do
expect(html).to include '<div aria-valuemax="100" aria-valuemin="0" aria-valuenow="30" class="progress-bar" role="progressbar" style="width: 30%">'
end

describe 'given the :label option' do
specify 'is not set, hides the label' do
expect(html).to include '<span class="sr-only">30%</span>'
end

context 'is set to false, hides the label' do
let(:options) { {label: false }}
it { expect(html).to include '<span class="sr-only">30%</span>' }
end

context 'is set to true, displays a label matching the percentage' do
let(:options) { {label: true }}
it { expect(html).to include '30%</div>' }
end

context 'is a string, displays the string as the label' do
let(:options) { {label: "Thirty percent" }}
it { expect(html).to include 'Thirty percent</div>' }
end
end

describe 'given the :context option' do
specify 'is not set, shows a default bar' do
expect(html).to include 'class="progress-bar"'
end

context 'is set to :success, shows a "success" bar' do
let(:options) { {context: :success} }
it { expect(html).to include 'class="progress-bar progress-bar-success"' }
end

context 'is set to :info, shows a "info" bar' do
let(:options) { {context: :info} }
it { expect(html).to include 'class="progress-bar progress-bar-info"' }
end

context 'is set to :warning, shows a "warning" bar' do
let(:options) { {context: :warning} }
it { expect(html).to include 'class="progress-bar progress-bar-warning"' }
end

context 'is set to :danger, shows a "danger" bar' do
let(:options) { {context: :danger} }
it { expect(html).to include 'class="progress-bar progress-bar-danger"' }
end
end

describe 'given the :striped option' do
specify 'is not set, shows a solid color bar' do
expect(html).to include 'class="progress-bar"'
end

context 'is set to false, shows a solid color bar' do
let(:options) { {striped: false} }
it { expect(html).to include 'class="progress-bar"' }
end

context 'is set to true, shows a striped color bar' do
let(:options) { {striped: true} }
it { expect(html).to include 'class="progress-bar progress-bar-striped"' }
end
end

describe 'given the :animated option' do
specify 'is not set, shows a static color bar' do
expect(html).to include 'class="progress-bar"'
end

context 'is set to false, shows a static color bar' do
let(:options) { {animated: false} }
it { expect(html).to include 'class="progress-bar"' }
end

context 'is set to true, shows an animated color bar' do
let(:options) { {animated: true} }
it { expect(html).to include 'class="progress-bar progress-bar-striped active"' }
end
end
end

context 'with an array of options' do
let(:html) { progress_bar [options_bar_1, options_bar_2] }
let(:options_bar_1) { {percentage: 20, context: :success, label: true} }
let(:options_bar_2) { {percentage: 30, animated: true, label: 'Current'} }

it 'displays a group of stacked progress bars with their options' do
expect(html).to match %r{^<div class="progress"><div.+aria-valuenow="20" class="progress-bar progress-bar-success".+style="width: 20%">20% \(success\)</div>\n<div.+aria-valuenow="30" class="progress-bar progress-bar-striped active".+style="width: 30%">Current</div></div>$}m
end
end
end

0 comments on commit 3b1ae16

Please sign in to comment.