Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from claudiob/add-progress-bar
Add progress_bar helper
- Loading branch information
Showing
5 changed files
with
185 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |