Skip to content

Commit

Permalink
Update parts accordion to Bootstrap 3
Browse files Browse the repository at this point in the history
* Bootstrap 3 uses collapsing panels to build an accordion:
http://getbootstrap.com/javascript/#collapse-examples
* Use a `js-` prefixed class as the handle for sortable items
* Upgrade jQuery UI library to work with newer jQuery (1.8.20 to
1.10.4) — only includes ui.sortable, ui.accordion and core
* Use a CSS animation for the yellow fade effect
  • Loading branch information
fofr committed May 30, 2014
1 parent ce7a242 commit 1d19dc7
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 54 deletions.
16 changes: 5 additions & 11 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,20 @@ $(function() {
// collapse the parts using the bootstrap accordion
$(".collapse").collapse();

var accordionSelector = ".js-sort-handle";
var sortable_opts = {
axis: "y",
handle: "a.accordion-toggle",
handle: accordionSelector,
stop: function(event, ui) {
$('.part').each(function (i, elem) {
$(elem).find('input.order').val(i + 1);
ui.item.find("a.accordion-toggle").addClass("highlight");
setTimeout(function() { $("a.accordion-toggle.highlight").removeClass("highlight") }, 20 )
ui.item.find(accordionSelector).addClass("yellow-fade");
});
}
}

$('#parts').sortable(sortable_opts)
.find("a.accordion-toggle").css({cursor: 'move'});

// simulate a click on the first part to open it
// TODO: This doesn't behave well as the accordion closes then opens rather
// than leaving the first part open.
// $('#parts .part .accordion-body').first().one('hidden', function(){
// $('#parts .part .accordion-body').first().collapse('show');
// });
.find(accordionSelector).css({cursor: 'move'});

$('body').
on('change', 'input.title', function () {
Expand Down
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@

@import "govuk_admin_template";
@import "scaffold";
@import "sortable_accordion";
31 changes: 31 additions & 0 deletions app/assets/stylesheets/sortable_accordion.css.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.ui-sortable .panel {
margin-bottom: 5px;
}

// 3s yellow fade animation
// Could be part of admin gem
// Based on http://jsfiddle.net/csswizardry/TVqVC/

@-webkit-keyframes yellow-fade {
5% {
background-color:#ff9;
}
}

@-moz-keyframes yellow-fade {
5% {
background-color:#ff9;
}
}

@keyframes yellow-fade {
5% {
background-color:#ff9;
}
}

.yellow-fade {
-webkit-animation:yellow-fade 3s;
-moz-animation:yellow-fade 3s;
animation:yellow-fade 3s;
}
38 changes: 19 additions & 19 deletions app/views/admin/editions/_part.html.erb
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
<div class="accordion-group part">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#parts" href="#<%= f.object.slug || 'untitled-part' %>">
<i class="icon-chevron-down"></i>
<%= f.object.title.present? ? f.object.title : 'Untitled part' %>
</a>
<div class="panel panel-default part">
<div class="panel-heading js-sort-handle">
<h4 class="panel-title" >
<a data-toggle="collapse" data-parent="#parts" href="#<%= f.object.slug || 'untitled-part' %>">
<i class="glyphicon glyphicon-chevron-down glyphicon-smaller-than-text add-right-margin pull-left"></i>
<%= f.object.title.present? ? f.object.title : 'Untitled part' %>
</a>
</h4>
</div>
<div id="<%= f.object.slug || 'untitled-part' %>" class="accordion-body <% if f.object.valid? %>collapse <% end %>in">
<div class="accordion-inner">

<div class="row">
<div id="<%= f.object.slug || 'untitled-part' %>" class="panel-collapse <% if f.object.valid? %>collapse <% end %>in">
<div class="panel-body">

<%= f.inputs do %>
<%= f.input :title,
:input_html => { :class => 'col-md-12 title', :disabled => ! editable },
:input_html => { :class => 'title', :disabled => ! editable },
:hint => true,
:required => true %>

<%= f.input :body,
:as => :text,
:required => true,
:input_html => { :class => 'col-md-12', :rows => '25', :disabled => ! editable } %>
:input_html => { :rows => '25', :disabled => ! editable } %>

<%= f.input :slug,
:input_html => { :class => 'col-md-12 slug', :disabled => ! editable },
:input_html => { :class => 'slug', :disabled => ! editable },
:hint => false,
:required => true %>

<p class="help-block"><i class="icon-info-sign"></i> Eg. title-of-part (no spaces, apostrophes, etc).</p>
<p class="help-block">
<i class="glyphicon glyphicon-info-sign"></i> eg title-of-part (no spaces, apostrophes, etc).
</p>

<%= f.input :order, :as => :hidden, :input_html => { :class => 'order', :disabled => !editable } %>

<% if editable %>
<div class="row">
<hr>
<%= f.remove_link "Remove this part" %>
</div><!--/.row -->
<hr>
<%= f.remove_link "Remove this part" %>
<% end %>
<% end %>
</div><!--/.row -->

</div>
</div>
</div>
2 changes: 1 addition & 1 deletion app/views/admin/editions/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
<hr>

<%= f.inputs :name => "Parts (govspeak available)" do %>
<section class="accordion" id="parts">
<section class="panel-group" id="parts">
<%= f.semantic_fields_for :parts, f.object.parts.in_order do |part| %>
<%= render :partial => '/admin/editions/part', :locals => {:f => part, :editable => @edition.draft?} %>
<% end %>
Expand Down
14 changes: 8 additions & 6 deletions spec/features/edition_edit_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -275,19 +275,21 @@

visit "/admin/editions/#{@edition._id}/edit"

page.should have_selector("#parts div.part:nth-of-type(1) .accordion-toggle", :text => "Wallace")
page.should have_selector("#parts div.part:nth-of-type(2) .accordion-toggle", :text => "Gromit")
page.should have_selector("#parts div.part:nth-of-type(3) .accordion-toggle", :text => "Cheese")
# Capybara nth-of-type tests need an element in their selector
# https://github.com/jnicklas/capybara/issues/1109
page.should have_selector("#parts div.part:nth-of-type(1) .panel-title a", :text => 'Wallace')
page.should have_selector("#parts div.part:nth-of-type(2) .panel-title a", :text => 'Gromit')
page.should have_selector("#parts div.part:nth-of-type(3) .panel-title a", :text => 'Cheese')

find(:css, "input#edition_parts_attributes_0_order").set "2"
find(:css, "input#edition_parts_attributes_1_order").set "0"
find(:css, "input#edition_parts_attributes_2_order").set "1"

click_on "Save"

page.should have_selector("#parts div.part:nth-of-type(1) .accordion-toggle", :text => "Gromit")
page.should have_selector("#parts div.part:nth-of-type(2) .accordion-toggle", :text => "Cheese")
page.should have_selector("#parts div.part:nth-of-type(3) .accordion-toggle", :text => "Wallace")
page.should have_selector("#parts div.part:nth-of-type(1) .panel-title a", :text => "Gromit")
page.should have_selector("#parts div.part:nth-of-type(2) .panel-title a", :text => "Cheese")
page.should have_selector("#parts div.part:nth-of-type(3) .panel-title a", :text => "Wallace")
end

scenario "save and publish an edition" do
Expand Down
23 changes: 6 additions & 17 deletions vendor/assets/javascripts/jquery-ui.custom.min.js

Large diffs are not rendered by default.

0 comments on commit 1d19dc7

Please sign in to comment.