Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial project layout. Vendored sass port of bootstrap. Started on i…

…nitial change to body & layout to create a style that shows the nav with twitters navbar
  • Loading branch information...
commit 6ea8d396d315f93eabee56579761010defe4b35a 0 parents
@andrewmp1 authored
Showing with 7,238 additions and 0 deletions.
  1. +10 −0 .gitignore
  2. +1 −0  .rspec
  3. +13 −0 Gemfile
  4. +26 −0 LICENSE
  5. +84 −0 README.md
  6. +29 −0 Rakefile
  7. +5 −0 Versionfile
  8. +1 −0  app/assets/javascripts/admin/spree_bootstrap_theme.js
  9. +3 −0  app/assets/javascripts/store/spree_bootstrap_theme.js
  10. +3 −0  app/assets/stylesheets/admin/spree_bootstrap_theme.css
  11. +191 −0 app/assets/stylesheets/store/_extras.css.scss
  12. +17 −0 app/assets/stylesheets/store/_forms.css.scss
  13. +191 −0 app/assets/stylesheets/store/_media_queries.css.scss
  14. +16 −0 app/assets/stylesheets/store/_navbar.css.scss
  15. +150 −0 app/assets/stylesheets/store/_products.css.scss
  16. +101 −0 app/assets/stylesheets/store/_spree_bootstrap_mixins.css.scss
  17. +421 −0 app/assets/stylesheets/store/_spree_core.css.scss
  18. 0  app/assets/stylesheets/store/_spree_variables.css.scss
  19. +5 −0 app/assets/stylesheets/store/spree_bootstrap.css.scss
  20. +3 −0  app/assets/stylesheets/store/spree_bootstrap_theme.css
  21. +6 −0 app/overrides/add_class_to_search.rb
  22. +51 −0 app/overrides/replace_body.rb
  23. +16 −0 lib/generators/spree_bootstrap_theme/install/install_generator.rb
  24. +2 −0  lib/spree_bootstrap_theme.rb
  25. +25 −0 lib/spree_bootstrap_theme/engine.rb
  26. +32 −0 spec/spec_helper.rb
  27. +26 −0 spree_bootstrap_theme.gemspec
  28. BIN  vendor/assets/images/glyphicons-halflings-white.png
  29. BIN  vendor/assets/images/glyphicons-halflings.png
  30. +91 −0 vendor/assets/javascripts/bootstrap-alert.js
  31. +98 −0 vendor/assets/javascripts/bootstrap-button.js
  32. +154 −0 vendor/assets/javascripts/bootstrap-carousel.js
  33. +136 −0 vendor/assets/javascripts/bootstrap-collapse.js
  34. +92 −0 vendor/assets/javascripts/bootstrap-dropdown.js
  35. +210 −0 vendor/assets/javascripts/bootstrap-modal.js
  36. +95 −0 vendor/assets/javascripts/bootstrap-popover.js
  37. +125 −0 vendor/assets/javascripts/bootstrap-scrollspy.js
  38. +130 −0 vendor/assets/javascripts/bootstrap-tab.js
  39. +270 −0 vendor/assets/javascripts/bootstrap-tooltip.js
  40. +51 −0 vendor/assets/javascripts/bootstrap-transition.js
  41. +271 −0 vendor/assets/javascripts/bootstrap-typeahead.js
  42. +12 −0 vendor/assets/javascripts/bootstrap.js
  43. +66 −0 vendor/assets/stylesheets/_bootstrap.scss
  44. +327 −0 vendor/assets/stylesheets/_responsive.scss
  45. +28 −0 vendor/assets/stylesheets/bootstrap/_accordion.scss
  46. +70 −0 vendor/assets/stylesheets/bootstrap/_alerts.scss
  47. +22 −0 vendor/assets/stylesheets/bootstrap/_breadcrumbs.scss
  48. +146 −0 vendor/assets/stylesheets/bootstrap/_button-groups.scss
  49. +165 −0 vendor/assets/stylesheets/bootstrap/_buttons.scss
  50. +121 −0 vendor/assets/stylesheets/bootstrap/_carousel.scss
  51. +18 −0 vendor/assets/stylesheets/bootstrap/_close.scss
  52. +44 −0 vendor/assets/stylesheets/bootstrap/_code.scss
  53. +18 −0 vendor/assets/stylesheets/bootstrap/_component-animations.scss
  54. +131 −0 vendor/assets/stylesheets/bootstrap/_dropdowns.scss
  55. +515 −0 vendor/assets/stylesheets/bootstrap/_forms.scss
  56. +8 −0 vendor/assets/stylesheets/bootstrap/_grid.scss
  57. +20 −0 vendor/assets/stylesheets/bootstrap/_hero-unit.scss
  58. +16 −0 vendor/assets/stylesheets/bootstrap/_labels.scss
  59. +17 −0 vendor/assets/stylesheets/bootstrap/_layouts.scss
  60. +519 −0 vendor/assets/stylesheets/bootstrap/_mixins.scss
  61. +73 −0 vendor/assets/stylesheets/bootstrap/_modals.scss
  62. +292 −0 vendor/assets/stylesheets/bootstrap/_navbar.scss
  63. +344 −0 vendor/assets/stylesheets/bootstrap/_navs.scss
  64. +30 −0 vendor/assets/stylesheets/bootstrap/_pager.scss
  65. +64 −0 vendor/assets/stylesheets/bootstrap/_pagination.scss
  66. +49 −0 vendor/assets/stylesheets/bootstrap/_popovers.scss
  67. +95 −0 vendor/assets/stylesheets/bootstrap/_progress-bars.scss
  68. +126 −0 vendor/assets/stylesheets/bootstrap/_reset.scss
  69. +29 −0 vendor/assets/stylesheets/bootstrap/_scaffolding.scss
  70. +156 −0 vendor/assets/stylesheets/bootstrap/_sprites.scss
  71. +139 −0 vendor/assets/stylesheets/bootstrap/_tables.scss
  72. +35 −0 vendor/assets/stylesheets/bootstrap/_thumbnails.scss
  73. +35 −0 vendor/assets/stylesheets/bootstrap/_tooltip.scss
  74. +217 −0 vendor/assets/stylesheets/bootstrap/_type.scss
  75. +23 −0 vendor/assets/stylesheets/bootstrap/_utilities.scss
  76. +100 −0 vendor/assets/stylesheets/bootstrap/_variables.scss
  77. +17 −0 vendor/assets/stylesheets/bootstrap/_wells.scss
10 .gitignore
@@ -0,0 +1,10 @@
+\#*
+*~
+.#*
+.DS_Store
+.idea
+.project
+tmp
+nbproject
+*.swp
+spec/dummy
1  .rspec
@@ -0,0 +1 @@
+--colour
13 Gemfile
@@ -0,0 +1,13 @@
+source 'http://rubygems.org'
+
+group :test do
+ gem 'ffaker'
+end
+
+if RUBY_VERSION < "1.9"
+ gem "ruby-debug"
+else
+ gem "ruby-debug19"
+end
+
+gemspec
26 LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2012 [name of plugin creator]
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name Spree nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
84 README.md
@@ -0,0 +1,84 @@
+SpreeBootstrapTheme
+===================
+
+Spree_bootstrap_theme is based on twitter's bootstrap project ported to sass.
+
+
+http://twitter.github.com/bootstrap/download.html#plugins
+
+
+Warning, alpha quality. Doesn't work yet!
+
+
+This project is being built against spree version 1.0 and greater
+
+
+Spree uses Skeleton as a lightweight css framework. With the different naming conventions in skeleton and spree with regards to bootstrap this project uses sass mixins as a bridge and where that doesn't completely work some deface overrides to views to enable bootstrap naming conventions.
+
+
+Some quick notes on the differences in the css markup conventions:
+
+
+| spree/skeleton | bootstrap |
+
+| :-----------------------: | :-----------------------: |
+
+| grid=960/16 | grid=940/12 |
+
+| button=.button | button=.btn |
+
+| flash=.flash | flash=.alert |
+
+
+
+Install
+=======
+
+gem 'spree_bootstrap_theme', :git => 'git://github.com/andrewmp1/spree_bootstrap_theme.git'
+NOTE: It's important that you add this line at the bottom of the Gemfile, or at least AFTER any other extension/engine/gem that you'd like to theme (i.e. Spree)
+
+Make sure you remove any includes in your stylesheets to the spree core stylesheets.
+
+From the bootstrap-sass page. The theme vendors bootstrap in the same way as the gem bootstrap-sass:
+
+# Notes from Bootstrap for SASS
+
+`bootstrap-sass` is an SASS-powered version of [Twitter's Bootstrap](http://github.com/twitter/bootstrap), ready to drop right into your SASS powered applications.
+
+Enjoy.
+
+## Usage
+
+#### CSS
+
+Import "bootstrap" in your SCSS file of choice to get all of Bootstrap's styles, mixins and variables! Don't use Sproket's `//= require` directives for SASS files, because they're horrible and will kill your cat.
+
+ @import "bootstrap";
+
+Need to configure a variable or two? Simple define the value of the variable you want to change *before* importing Bootstrap. SASS will be awesome and respect your existing definition rather than overwriting it with the Bootstrap defaults. A list of customisable variables can be found in the [Bootstrap documentation](http://twitter.github.com/bootstrap/less.html#variables).
+
+ $primaryButtonBackground: #f00;
+ @import "bootstrap";
+
+#### Javascripts
+
+You can include the Bootstrap javascripts through two methods. In this case, Sproket's `//= require` directives are useful and will not cause feline death.
+
+We have a helper that includes all available javascripts:
+
+ // Loads all Bootstrap javascripts
+ //= require bootstrap
+
+You can also load individual modules, provided you sort out any related dependencies.
+
+ //= require bootstrap-scrollspy
+ //= require bootstrap-modal
+ //= require bootstrap-dropdown
+
+Testing
+-------
+
+#TODO
+
+
+Copyright (c) 2012 Drew Purdy, released under the New BSD License
29 Rakefile
@@ -0,0 +1,29 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/packagetask'
+require 'rubygems/package_task'
+require 'rspec/core/rake_task'
+require 'spree/core/testing_support/common_rake'
+
+RSpec::Core::RakeTask.new
+
+task :default => [:spec]
+
+spec = eval(File.read('spree_bootstrap_theme.gemspec'))
+
+Gem::PackageTask.new(spec) do |p|
+ p.gem_spec = spec
+end
+
+desc "Release to gemcutter"
+task :release => :package do
+ require 'rake/gemcutter'
+ Rake::Gemcutter::Tasks.new(spec).define
+ Rake::Task['gem:push'].invoke
+end
+
+desc "Generates a dummy app for testing"
+task :test_app do
+ ENV['LIB_NAME'] = 'spree_bootstrap_theme'
+ Rake::Task['common:test_app'].invoke
+end
5 Versionfile
@@ -0,0 +1,5 @@
+# This file is used to designate compatibilty with different versions of Spree
+# Please see http://spreecommerce.com/documentation/extensions.html#versionfile for details
+
+"1.0.x" => { :branch => "master"}
+
1  app/assets/javascripts/admin/spree_bootstrap_theme.js
@@ -0,0 +1 @@
+//= require admin/spree_core
3  app/assets/javascripts/store/spree_bootstrap_theme.js
@@ -0,0 +1,3 @@
+//= require bootstrap
+//= require_tree .
+
3  app/assets/stylesheets/admin/spree_bootstrap_theme.css
@@ -0,0 +1,3 @@
+/*
+ *= require admin/spree_core
+*/
191 app/assets/stylesheets/store/_extras.css.scss
@@ -0,0 +1,191 @@
+/*--------------------------------------*/
+/* Main search bar
+/*--------------------------------------*/
+#search-bar {
+ display: block;
+}
+
+/*--------------------------------------*/
+/* Navigation
+/*--------------------------------------*/
+nav#top-nav-bar {
+ text-align: right;
+ margin-top: 20px;
+
+ ul {
+ li {
+ margin-bottom: 5px;
+ padding-left: 10px;
+
+ a{
+ font-weight: bold;
+ font-size: 14px;
+ text-transform: uppercase;
+ }
+ }
+ }
+}
+
+nav #main-nav-bar {
+ text-transform: uppercase;
+ font-weight: bold;
+ margin-top: 20px;
+ border-bottom: 1px solid $c_border;
+ padding-bottom: 6px;
+
+ li {
+ a {
+ font-size: 16px;
+ padding: 5px;
+ }
+
+ &#link-to-cart {
+ float: right;
+ padding-left: 24px;
+ background: url("cart.png") no-repeat left center;
+
+ &:hover {
+ border-color: $c_colored;
+
+ .amount {
+ border-color: $c_colored;
+ }
+ }
+
+ a {
+ font-weight: normal;
+ font-size: 16px;
+ color: $c_colored;
+
+ .amount {
+ font-size: 18px;
+ font-weight: bold;
+ border-left: 1px solid $c_border;
+ padding-left: 5px;
+ padding-bottom: 8px;
+ }
+ }
+ }
+ }
+}
+
+nav#taxonomies {
+ .taxonomy-root {
+ text-transform: uppercase;
+ border-bottom: 1px solid $c_border;
+ margin-bottom: 5px;
+ color: $c_colored;
+ }
+
+ .taxons-list {
+ padding-left: 20px;
+ margin-bottom: 20px;
+ list-style: disc outside;
+ }
+}
+
+/*--------------------------------------*/
+/* Forms
+/*--------------------------------------*/
+textarea, input[type="date"],
+input[type="datetime"], input[type="datetime-local"],
+input[type="email"], input[type="month"], input[type="number"],
+input[type="password"], input[type="search"], input[type="tel"],
+input[type="text"], input[type="time"], input[type="url"],
+input[type="week"] {
+ border: 1px solid $c_border;
+ padding: 2px 5px;
+ font-family: "Ubuntu", sans-serif;
+
+ &:active, &:focus {
+ border-color: $c_colored;
+ outline: none;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ -o-box-shadow: none;
+ box-shadow: none;
+ }
+
+ &.error {
+ border-color: $c_red;
+ }
+}
+
+select {
+ border: 1px solid $c_border;
+ font-family: "Ubuntu", sans-serif;
+ background-image: url('select_arrow.gif');
+ background-repeat: no-repeat;
+ background-position: right center;
+
+ &:active, &:focus {
+ @extend input[type="text"]:focus
+ }
+}
+
+label.error {
+ display: block;
+ font-size: 11px;
+ color: $c_red;
+ margin-top: 3px;
+}
+
+input[type="submit"], input[type="button"],
+input[type= "reset"], button, a.button {
+ background-color: $c_colored;
+ background-image: none;
+ text-shadow: none;
+ color: white;
+ font-weight: bold;
+ font-family: "Ubuntu", sans-serif;
+ border: 1px solid rgba(0, 138, 189, .75);
+ -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
+ -khtml-box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
+ -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
+ -ms-box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
+ -o-box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
+ box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
+ -webkit-border-radius: 0px;
+ -khtml-border-radius: 0px;
+ -moz-border-radius: 0px;
+ -ms-border-radius: 0px;
+ -o-border-radius: 0px;
+ border-radius: 0px;
+
+ // font-size: 13px;
+ vertical-align: text-top;
+
+ &.large {
+ padding: 7px 10px;
+ font-size: 14px;
+ }
+
+ &:hover {
+ background-image: none;
+ background-color: $c_base;
+ border-color: $c_base;
+ color: white !important;
+ }
+}
+
+.ie8 {
+ a.button {
+ line-height: 16px;
+ }
+}
+
+input[type="checkbox"], input[type="button"],
+input[type="submit"], input[type="reset"],
+button, label {
+ vertical-align: middle;
+}
+
+a.button {
+ display: inline-block;
+ line-height: 15px;
+ margin-top: -2px;
+ vertical-align: bottom;
+}
+
+
+
17 app/assets/stylesheets/store/_forms.css.scss
@@ -0,0 +1,17 @@
+/*--------------------------------------*/
+/* Forms
+/*--------------------------------------*/
+textarea, input[type="date"],
+input[type="datetime"], input[type="datetime-local"],
+input[type="email"], input[type="month"], input[type="number"],
+input[type="password"], input[type="search"], input[type="tel"],
+input[type="text"], input[type="time"], input[type="url"],
+input[type="week"] {
+ border: 1px solid $c_border;
+ padding: 2px 5px;
+ font-family: "Ubuntu", sans-serif;
+
+ &.error {
+ border-color: $c_red;
+ }
+}
191 app/assets/stylesheets/store/_media_queries.css.scss
@@ -0,0 +1,191 @@
+
+/* #Media Queries
+================================================== */
+
+ /* Smaller than standard 960 (devices and browsers) */
+ @media only screen and (max-width: 959px) {}
+
+ /* Tablet Portrait size to standard 960 (devices and browsers) */
+ @media only screen and (min-width: 768px) and (max-width: 959px) {}
+
+ /* All Mobile Sizes (devices and browser) */
+ @media only screen and (max-width: 767px) {
+ nav#taxonomies {
+ text-align: center;
+
+ ul {
+ padding-left: 0 !important;
+ list-style: none !important;
+ }
+ }
+
+ ul#nav-bar {
+ text-align: center;
+ }
+
+ .steps-data div.columns {
+ margin-bottom: 15px;
+ text-align: center;
+ }
+
+ #order_details, #order {
+ table[data-hook="order_details"] {
+ width: 100%;
+ }
+ }
+
+ #update-cart {
+ #subtotal, .links {
+ width: 50%;
+ float: left;
+ text-align: left;
+ }
+ #subtotal {
+ text-align: right;
+ }
+ }
+ }
+
+ /* Mobile Landscape Size to Tablet Portrait (devices and browsers) */
+ @media only screen and (min-width: 480px) and (max-width: 767px) {
+
+ input, select {
+ vertical-align: baseline !important;
+ }
+
+ figure#logo {
+ text-align: center;
+ }
+
+ #link-to-login {
+ display: block;
+ text-align: center;
+ }
+
+ #search-bar {
+ display: block;
+ text-align: center;
+
+ select {
+ margin-bottom: 10px;
+ }
+ }
+
+ ul#products {
+ margin-left: 0;
+ margin-right: -20px;
+
+ li {
+ width: 133px;
+ margin-right: 10px;
+ }
+ }
+
+ }
+
+
+ /* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */
+ @media only screen and (max-width: 479px) {
+
+ .progress-steps li {
+ padding: 0;
+ margin: 0;
+ width: 50%;
+
+ span {
+ display: block;
+ padding: 10px 20px;
+ }
+ }
+
+ #shipping_method p label {
+ float: none;
+ display: block;
+ text-align: center;
+ margin-right: 0;
+ }
+
+ p[data-hook="use_billing"] {
+ float: none;
+ margin-top: 0;
+ }
+
+ table#cart-detail {
+ tbody {
+ tr {
+ td[data-hook="cart_item_description"] {
+ padding: 0 !important;
+ text-indent: -9999px;
+
+ h4 {
+ display: none;
+ }
+ }
+ td[data-hook="cart_item_image"] {
+ img {
+ width: 70px;
+ }
+ }
+ td[data-hook="cart_item_price"], td[data-hook="cart_item_total"] {
+ font-size: 14px !important;
+ }
+ }
+ }
+ }
+
+ table.order-summary {
+ display: block; position: relative; width: 100%;
+
+ thead { display: block; float: left; }
+ tbody { display: block; width: auto; position: relative; overflow-x: auto; white-space: nowrap; }
+ thead tr { display: block; }
+ th { display: block; }
+ tbody tr { display: inline-block; vertical-align: top; }
+ td { display: block; min-height: 1.25em; }
+ }
+
+
+ figure#logo {
+ text-align: center;
+ }
+
+ #link-to-login {
+ display: block;
+ text-align: center;
+ }
+
+ #search-bar {
+ display: block;
+ text-align: center;
+
+ select {
+ margin-bottom: 10px;
+ }
+ }
+
+ aside#sidebar {
+ text-align: center;
+
+ ul {
+ padding-left: 0 !important;
+
+ li {
+ list-style-type: none;
+ }
+ }
+ }
+
+ ul#products {
+ margin-left: 0;
+
+ li {
+ width: 140px;
+ margin-right: 15px;
+ }
+ }
+
+ #content {
+ text-align: center;
+ }
+
+ }
16 app/assets/stylesheets/store/_navbar.css.scss
@@ -0,0 +1,16 @@
+.navbar {
+ ul{
+ display: inline;
+ }
+ li{
+ display: inline;
+ }
+ a{
+ display: inline;
+ }
+}
+
+
+#wrapper {
+ padding-top: 40px;
+}
150 app/assets/stylesheets/store/_products.css.scss
@@ -0,0 +1,150 @@
+/*--------------------------------------*/
+/* Products
+/*--------------------------------------*/
+.product-section-title {
+ text-transform: uppercase;
+ color: $c_colored;
+ margin-top: 15px;
+}
+
+.add-to-cart {
+ margin-top: 15px;
+
+ input[type="number"] {
+ width: 60px;
+ vertical-align: middle;
+ padding: 5px;
+ height: 35px;
+ }
+}
+
+span.price {
+ font-weight: bold;
+ color: $c_colored;
+
+ &.selling {
+ font-size: 20px;
+ }
+ &.diff {
+ font-weight: bold
+ }
+}
+
+ul#products {
+ margin-left: -10px;
+ margin-right: -10px;
+
+ li {
+ text-align: center;
+ font-weight: bold;
+ margin-bottom: 20px;
+
+ a {
+ display: block;
+
+ &.info {
+ height: 35px;
+ margin-top: 5px;
+ color: $c_gray1;
+ border-bottom: 1px solid $c_border;
+ }
+ }
+
+ .product-image {
+ border: 1px solid $c_border;
+ padding: 5px;
+ min-height: 110px;
+
+ &:hover {
+ border-color: $c_colored;
+ }
+
+ }
+
+ .price {
+ color: $c_colored;
+ font-size: 16px;
+ padding-top: 5px;
+ display: block;
+ }
+ }
+}
+
+.subtaxon-title {
+ text-transform: uppercase;
+
+ a {
+ color: $c_colored;
+ }
+}
+
+.search-results-title {
+ text-transform: uppercase;
+ border-bottom: 1px solid $c_border;
+ margin-bottom: 10px;
+}
+
+#sidebar_products_search {
+ .navigation {
+ margin-bottom: 15px;
+ }
+
+ span.category {
+ display: block;
+ font-weight: bold;
+ text-transform: uppercase;
+ border-bottom: 1px solid #ededed;
+ margin-bottom: 5px;
+ color: #00adee;
+ font-size: 14px;
+ line-height: 24px;
+ }
+}
+
+.taxon {
+ overflow: hidden;
+}
+
+#product-images {
+ #main-image {
+ text-align: center;
+ border: 1px solid $c_border;
+ }
+}
+
+#product-description {
+ .product-title {
+ border-bottom: 1px solid $c_border;
+ margin-bottom: 15px;
+ }
+}
+
+#product-thumbnails {
+ margin-top: 10px;
+
+ li {
+ margin-right: 6px;
+ border: 1px solid $c_border;
+
+ img {
+ padding: 5px;
+ }
+
+ &:hover, &.selected {
+ border-color: $c_colored;
+ }
+ }
+}
+
+#product-properties {
+ border: 1px solid $c_border;
+ padding: 10px;
+}
+
+#product-variants {
+ ul {
+ li {
+ padding: 5px;
+ }
+ }
+}
101 app/assets/stylesheets/store/_spree_bootstrap_mixins.css.scss
@@ -0,0 +1,101 @@
+/* This file wraps bootstraps class names
+ to match spree's default class naming
+ scheme for things like buttons,
+/* flash messages, etc. Any bootstrap */
+/* variables defined here will override */
+/* default values */
+/*--------------------------------------*/
+/* Colors
+/*--------------------------------------*/
+$c_base: #404042; /* Dark gray */
+$c_gray1: #bbbbbb; /* Mid light gray */
+$c_colored: #00ADEE; /* Light blue */
+$c_colored_alt: #f0f8ff; /* Lighter blue */
+$c_border: #dedede; /* Light gray */
+$c_green: #8dba53; /* Spree green */
+$c_red: #e45353; /* Error red */
+
+/* require bootstrap files for mixins */
+
+@import "bootstrap/variables";
+@import "bootstrap/mixins";
+@import "bootstrap/alerts";
+@import "bootstrap/buttons";
+
+
+/*------------------------------------------------------*/
+/* Changes to the default bootstrap variables */
+/*------------------------------------------------------*/
+$gridColumns: 16;
+$gridColumnWidth: 40px;
+
+// Navbar
+$navbarHeight: 30px;
+$navbarBackground: $blueDark;
+$navbarBackgroundHighlight: $blue;
+
+$navbarText: $grayLight;
+$navbarLinkColor: $grayLight;
+$navbarLinkColorHover: $white;
+
+/* Flash alerts Spree uses flash.notice, .success & .error */
+/*--------------------------------------*/
+/* Flash messages
+/*--------------------------------------*/
+.flash {
+ @extend .alert;
+
+ &.notice {
+ @extend .alert-info;
+ }
+ &.success {
+ @extend .alert-success;
+ }
+ &.error {
+ @extend .alert-error;
+ }
+}
+
+.errorExplanation {
+ @extend .flash.error;
+ @extend .flash;
+
+ p {
+ font-weight: normal;
+ }
+
+ ul {
+ list-style: disc outside;
+ margin-left: 30px;
+
+ li {
+ font-weight: normal;
+ }
+ }
+}
+
+/* Buttons */
+
+input[type="submit"], input[type="button"],
+input[type= "reset"], button, a.button {
+ @extend .btn;
+}
+
+/* Breadcrumb */
+
+/* Spree uses ol Bootstrap uses ul */
+/* Spree's progress-steps are > bootstraps */
+
+/* Forms */
+
+
+/* Tables */
+
+@import "bootstrap";
+
+
+
+
+
+
+
421 app/assets/stylesheets/store/_spree_core.css.scss
@@ -0,0 +1,421 @@
+/*--------------------------------------*/
+/* Basic styles
+/*--------------------------------------*/
+body {
+ font-family: 'Ubuntu', sans-serif;
+ color: $c_base;
+ line-height: 18px;
+ font-size: 12px;
+}
+
+#breadcrumbs {
+ border-bottom: 1px solid $c_border;
+ padding: 3px 0;
+ margin-bottom: 15px;
+
+ li {
+ a {
+ color: $c_colored;
+ }
+ span {
+ text-transform: uppercase;
+ font-weight: bold;
+ }
+ }
+}
+
+/* Custom text-selection colors (remove any text shadows: twitter.com/miketaylr/status/12228805301) */
+::-moz-selection{background: $c_colored; color: white; text-shadow: none;}
+::selection {background: $c_colored; color: white; text-shadow: none;}
+
+/* j.mp/webkit-tap-highlight-color */
+a:link {-webkit-tap-highlight-color: $c_colored;}
+
+ins {background-color: $c_colored; color: white; text-decoration: none;}
+mark {background-color: $c_colored; color: white; font-style: italic; font-weight: bold;}
+
+ /*--------------------------------------*/
+ /* Links
+ /*--------------------------------------*/
+ a {
+ text-decoration: none;
+ color: $c_base;
+
+ &:hover {
+ color: $c_colored !important;
+ }
+ }
+
+ /*--------------------------------------*/
+ /* Lists
+ /*--------------------------------------*/
+ ul, ol {
+ li {
+
+ }
+
+ &.inline {
+ li {
+ display: inline-block;
+ }
+ }
+ }
+
+
+ dl {
+ dt, dd {
+ display: inline-block;
+ width: 50%;
+ padding: 5px;
+
+ &.odd {
+ background-color: $c_border;
+ }
+ }
+ dt {
+ font-weight: bold;
+ text-transform: uppercase;
+ }
+ dd {
+ margin-left: -23px;
+ }
+ }
+
+
+ /*--------------------------------------*/
+ /* Headers
+ /*--------------------------------------*/
+ h1, h2, h3, h4, h5, h6 {
+ font-weight: bold;
+ }
+ h1 { font-size: 24px; line-height: 34px; }
+ h2 { font-size: 23px; line-height: 32px; }
+ h3 { font-size: 20px; line-height: 30px; }
+ h4 { font-size: 18px; line-height: 28px; }
+ h5 { font-size: 16px; line-height: 26px; }
+ h6 { font-size: 14px; line-height: 24px; }
+
+
+
+
+ /*--------------------------------------*/
+ /* Footer
+ /*--------------------------------------*/
+ footer#footer {
+ padding: 10px 0;
+ border-top: 1px solid $c_border;
+ }
+
+ /*--------------------------------------*/
+ /* Paragraphs
+ /*--------------------------------------*/
+ p {
+ padding: 10px 0;
+ }
+
+ /*--------------------------------------*/
+ /* Tables
+ /*--------------------------------------*/
+ table {
+ thead {
+ background-color: $c_border;
+ text-transform: uppercase;
+
+ tr {
+ th {
+ padding: 5px 10px;
+ }
+ }
+ }
+
+ tbody, tfoot {
+ tr {
+ border-bottom: 1px solid $c_border;
+
+ td {
+ vertical-align: middle;
+ padding: 5px 10px;
+ }
+
+ &.alt, &.odd {
+ background-color: $c_colored_alt;
+ }
+ }
+ }
+ }
+
+
+ /*--------------------------------------*/
+ /* Checkout
+ /*--------------------------------------*/
+ .progress-steps {
+ list-style: decimal inside;
+ overflow: auto;
+
+ li {
+ float: left;
+ margin-right: 20px;
+ font-weight: bold;
+ text-transform: uppercase;
+ padding: 5px 20px;
+ color: $c_gray1;
+
+ &.current-first, &.current {
+ background-color: $c_colored;
+ color: white;
+ }
+
+ &.completed-first, &.completed {
+ background-color: $c_border;
+ color: white;
+
+ a {
+ color: white;
+ }
+
+ &:hover {
+ background-color: $c_colored;
+ color: white;
+
+ a {
+ color: white;
+
+ &:hover {
+ color: white !important;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ #checkout-summary {
+ text-align: center;
+ border: 1px solid $c_border;
+ margin-top: 23px;
+
+ h3 {
+ text-transform: uppercase;
+ font-size: 14px;
+ color: $c_colored;
+ border-bottom: 1px solid $c_border;
+ }
+
+ table {
+ width: 100%;
+
+ tr[data-hook="item_total"] {
+ td:last-child {
+ strong {
+ @extend span.price;
+ }
+ }
+ }
+
+ tr[data-hook="order_total"] {
+ border-bottom: none;
+ };
+
+ #summary-order-total {
+ @extend span.price;
+ font-size: 14px;
+ }
+ }
+ }
+
+ #billing, #shipping, #shipping_method,
+ #payment, #order_details, #order_summary {
+ margin-top: 10px;
+ border: 1px solid $c_border;
+ padding: 10px;
+
+ legend {
+ text-transform: uppercase;
+ font-weight: bold;
+ font-size: 14px;
+ color: $c_colored;
+ padding: 5px;
+ margin-left: 15px;
+ }
+ }
+
+ #order_details, #order_summary {
+ padding: 0;
+
+ div:last-child {
+ margin-left: -1px;
+ }
+
+ .payment-info {
+ .cc-type {
+ img {
+ vertical-align: middle;
+ }
+ }
+ }
+
+ td.price, td.total {
+ span {
+ @extend span.price;
+ }
+ }
+
+ table tfoot {
+ text-align: right;
+ color: $c_gray1;
+
+ tr {
+ border: none;
+ }
+
+ &#order-total {
+ text-transform: uppercase;
+ font-size: 16px;
+ color: $c_base;
+
+ tr {
+ border-top: 1px solid $c_border;
+
+ td {
+ padding: 10px;
+ }
+ }
+ }
+ }
+
+ .steps-data {
+ padding: 10px;
+
+ h6 {
+ border-bottom: 1px solid $c_border;
+ margin-bottom: 5px;
+ }
+ }
+ }
+
+ #shipping_method {
+ p {
+ label {
+ float: left;
+ font-weight: bold;
+ font-size: 14px;
+ margin-right: 40px;
+ padding: 5px;
+ }
+ }
+ }
+
+ p[data-hook="use_billing"] {
+ float: right;
+ margin-top: -38px;
+ background-color: white;
+ padding: 5px;
+ }
+
+ /*--------------------------------------*/
+ /* Cart
+ /*--------------------------------------*/
+ table#cart-detail {
+ width: 100%;
+ tbody#line_items {
+ tr {
+
+ td[data-hook="cart_item_price"], td[data-hook="cart_item_total"] {
+ @extend span.price;
+ @extend span.price.selling;
+ }
+ td[data-hook="cart_item_quantity"] {
+ .line_item_quantity {
+ width: 40px;
+ }
+ }
+ td[data-hook="cart_item_delete"] {
+ .delete {
+ display: block;
+ width: 20px;
+ }
+ }
+ }
+ }
+ }
+
+ div[data-hook="inside_cart_form"] {
+ .links {
+ margin-top: 15px;
+ }
+
+ #subtotal {
+ text-align: right;
+ text-transform: uppercase;
+ margin-top: 10px;
+
+ span.order-total {
+ @extend span.price;
+ }
+ }
+ }
+
+ #empty-cart {
+ margin-top: 15px;
+ float: right;
+ }
+
+ /*--------------------------------------*/
+ /* Account
+ /*--------------------------------------*/
+ #existing-customer, #new-customer, #forgot-password {
+ h6 {
+ text-transform: uppercase;
+ color: $c_colored;
+ }
+ }
+
+ #registration {
+ h6 {
+ text-transform: uppercase;
+ color: $c_colored;
+ }
+
+ #existing-customer {
+ width: auto;
+ text-align: left;
+ }
+ }
+
+ #user-info {
+ margin-bottom: 15px;
+ border: 1px solid $c_border;
+ padding: 10px;
+ }
+
+ /*--------------------------------------*/
+ /* Order
+ /*--------------------------------------*/
+ #order_summary {
+ margin-top: 0;
+ }
+ #order {
+ p[data-hook="links"] {
+ margin-left: 10px;
+ overflow: auto;
+ }
+ }
+
+ table.order-summary {
+ tbody {
+ tr {
+ td {
+ width: 10%;
+ text-align: center;
+
+ &:first-child {
+ a {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: $c_colored;
+ }
+ }
+ }
+ }
+ }
+ }
0  app/assets/stylesheets/store/_spree_variables.css.scss
No changes.
5 app/assets/stylesheets/store/spree_bootstrap.css.scss
@@ -0,0 +1,5 @@
+@import "store/spree_bootstrap_mixins";
+@import "store/media_queries";
+@import "store/products";
+@import "store/forms";
+@import "store/navbar";
3  app/assets/stylesheets/store/spree_bootstrap_theme.css
@@ -0,0 +1,3 @@
+/*
+ *= require store/spree_bootstrap
+*/
6 app/overrides/add_class_to_search.rb
@@ -0,0 +1,6 @@
+Deface::Override.new(:virtual_path => %q{spree/app/views/shared/search},
+ :name => %q{add_class_to_search},
+ :replace => %q{},
+ :text => %q{<form class="navbar-search pull-right">
+ <input type="text" class="search-query" placeholder="Search">
+</form>})
51 app/overrides/replace_body.rb
@@ -0,0 +1,51 @@
+Deface::Override.new(:virtual_path => %q{spree/layouts/spree_application},
+ :name => %q{replace_body},
+ :replace => %q{[data-hook='body']},
+ :text => %q{<body class="<%= body_class %>" id="<%= @body_id || 'default' %>" data-hook="body">
+ <header id="header data-hook>
+ <div class="navbar navbar-fixed-top">
+ <div class="navbar-inner">
+ <div class="container">
+ <ul class="nav">
+ <li> <%= logo %> </li>
+ <li> Search </li>
+ <li id="link-to-cart" data-hook> Cart </li>
+ <li id="link-to-login"> <a href="/login">Login</a> </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </header>
+
+ <div class="container">
+
+ <div id="wrapper" class="row" data-hook>
+ <div class="span12"
+ <% if content_for?(:sidebar) %>
+ <div class='row span4'>
+ <aside id="sidebar" class="" data-hook>
+ <%= yield :sidebar %>
+ </aside>
+ </div>
+ <% end %>
+
+ <div id="content" class="row <% if !content_for?(:sidebar) %> span16 <% else %> span12 <% end %>" data-hook>
+ <%= breadcrumbs(@taxon) %>
+ <%= flash_messages %>
+ <%= yield %>
+ </div>
+ </div>
+ </div>
+
+ <footer id="footer" class="row" data-hook>
+ <div id="footer-left" class="columns alpha eight" data-hook>
+ <p><%= t(:powered_by) %> <%= link_to 'Spree', 'http://spreecommerce.com/' %></p>
+ </div>
+ <div id="footer-right" class="columns omega eight" data-hook></div>
+ </footer>
+
+ </div>
+
+ <%= render :partial => 'spree/shared/google_analytics' %>
+
+ </body>})
16 lib/generators/spree_bootstrap_theme/install/install_generator.rb
@@ -0,0 +1,16 @@
+module SpreeBootstrapTheme
+ module Generators
+ class InstallGenerator < Rails::Generators::Base
+
+ def add_javascripts
+ append_file "app/assets/javascripts/store/all.js", "//= require store/spree_bootstrap_theme\n"
+ append_file "app/assets/javascripts/admin/all.js", "//= require admin/spree_bootstrap_theme\n"
+ end
+
+ def add_stylesheets
+ inject_into_file "app/assets/stylesheets/store/all.css", " *= require store/spree_bootstrap_theme\n", :before => /\*\//, :verbose => true
+ inject_into_file "app/assets/stylesheets/admin/all.css", " *= require admin/spree_bootstrap_theme\n", :before => /\*\//, :verbose => true
+ end
+ end
+ end
+end
2  lib/spree_bootstrap_theme.rb
@@ -0,0 +1,2 @@
+require 'spree_core'
+require 'spree_bootstrap_theme/engine'
25 lib/spree_bootstrap_theme/engine.rb
@@ -0,0 +1,25 @@
+module SpreeBootstrapTheme
+ class Engine < Rails::Engine
+ engine_name 'spree_bootstrap_theme'
+
+ config.autoload_paths += %W(#{config.root}/lib)
+
+ # use rspec for tests
+ config.generators do |g|
+ g.test_framework :rspec
+ end
+
+ def self.activate
+ Dir.glob(File.join(File.dirname(__FILE__), "../../app/**/*_decorator*.rb")) do |c|
+ Rails.configuration.cache_classes ? require(c) : load(c)
+ end
+
+ # Load extension's view overrides
+ Dir.glob(File.join(File.dirname(__FILE__), "../../app/overrides/*.rb")) do |c|
+ Rails.configuration.cache_classes ? require(c) : load(c)
+ end
+ end
+
+ config.to_prepare &method(:activate).to_proc
+ end
+end
32 spec/spec_helper.rb
@@ -0,0 +1,32 @@
+# Configure Rails Environment
+ENV["RAILS_ENV"] = "test"
+
+require File.expand_path("../dummy/config/environment.rb", __FILE__)
+
+require 'rspec/rails'
+
+# Requires supporting ruby files with custom matchers and macros, etc,
+# in spec/support/ and its subdirectories.
+Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each {|f| require f }
+
+# Requires factories defined in spree_core
+require 'spree/core/testing_support/factories'
+
+RSpec.configure do |config|
+ # == Mock Framework
+ #
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
+ #
+ # config.mock_with :mocha
+ # config.mock_with :flexmock
+ # config.mock_with :rr
+ config.mock_with :rspec
+
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
+
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
+ # examples within a transaction, remove the following line or assign false
+ # instead of true.
+ config.use_transactional_fixtures = true
+end
26 spree_bootstrap_theme.gemspec
@@ -0,0 +1,26 @@
+# encoding: UTF-8
+Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = 'spree_bootstrap_theme'
+ s.version = '0.1.0'
+ s.summary = 'Spree theme based on twitter\'s bootstrap'
+ s.description = 'TODO: Add (optional) gem description here'
+ s.required_ruby_version = '>= 1.8.7'
+
+ s.author = 'Drew Purdy'
+ s.email = 'andrewmp1@gmail.com'
+ #s.homepage = 'http://www.spreecommerce.com'
+
+ #s.files = `git ls-files`.split("\n")
+ #s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ s.require_path = 'lib'
+ s.requirements << 'none'
+
+ s.add_dependency 'spree_core'
+
+ s.add_development_dependency 'capybara', '1.0.1'
+ s.add_development_dependency 'factory_girl'
+ s.add_development_dependency 'ffaker'
+ s.add_development_dependency 'rspec-rails', '~> 2.7'
+ s.add_development_dependency 'sqlite3'
+end
BIN  vendor/assets/images/glyphicons-halflings-white.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  vendor/assets/images/glyphicons-halflings.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
91 vendor/assets/javascripts/bootstrap-alert.js
@@ -0,0 +1,91 @@
+/* ==========================================================
+ * bootstrap-alert.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function( $ ){
+
+ "use strict"
+
+ /* ALERT CLASS DEFINITION
+ * ====================== */
+
+ var dismiss = '[data-dismiss="alert"]'
+ , Alert = function ( el ) {
+ $(el).on('click', dismiss, this.close)
+ }
+
+ Alert.prototype = {
+
+ constructor: Alert
+
+ , close: function ( e ) {
+ var $this = $(this)
+ , selector = $this.attr('data-target')
+ , $parent
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ $parent = $(selector)
+ $parent.trigger('close')
+
+ e && e.preventDefault()
+
+ $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
+
+ $parent.removeClass('in')
+
+ function removeElement() {
+ $parent.remove()
+ $parent.trigger('closed')
+ }
+
+ $.support.transition && $parent.hasClass('fade') ?
+ $parent.on($.support.transition.end, removeElement) :
+ removeElement()
+ }
+
+ }
+
+
+ /* ALERT PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.alert = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('alert')
+ if (!data) $this.data('alert', (data = new Alert(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ $.fn.alert.Constructor = Alert
+
+
+ /* ALERT DATA-API
+ * ============== */
+
+ $(function () {
+ $('body').on('click.alert.data-api', dismiss, Alert.prototype.close)
+ })
+
+}( window.jQuery )
98 vendor/assets/javascripts/bootstrap-button.js
@@ -0,0 +1,98 @@
+/* ============================================================
+ * bootstrap-button.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+!function( $ ){
+
+ "use strict"
+
+ /* BUTTON PUBLIC CLASS DEFINITION
+ * ============================== */
+
+ var Button = function ( element, options ) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.button.defaults, options)
+ }
+
+ Button.prototype = {
+
+ constructor: Button
+
+ , setState: function ( state ) {
+ var d = 'disabled'
+ , $el = this.$element
+ , data = $el.data()
+ , val = $el.is('input') ? 'val' : 'html'
+
+ state = state + 'Text'
+ data.resetText || $el.data('resetText', $el[val]())
+
+ $el[val](data[state] || this.options[state])
+
+ // push to event loop to allow forms to submit
+ setTimeout(function () {
+ state == 'loadingText' ?
+ $el.addClass(d).attr(d, d) :
+ $el.removeClass(d).removeAttr(d)
+ }, 0)
+ }
+
+ , toggle: function () {
+ var $parent = this.$element.parent('[data-toggle="buttons-radio"]')
+
+ $parent && $parent
+ .find('.active')
+ .removeClass('active')
+
+ this.$element.toggleClass('active')
+ }
+
+ }
+
+
+ /* BUTTON PLUGIN DEFINITION
+ * ======================== */
+
+ $.fn.button = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('button')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('button', (data = new Button(this, options)))
+ if (option == 'toggle') data.toggle()
+ else if (option) data.setState(option)
+ })
+ }
+
+ $.fn.button.defaults = {
+ loadingText: 'loading...'
+ }
+
+ $.fn.button.Constructor = Button
+
+
+ /* BUTTON DATA-API
+ * =============== */
+
+ $(function () {
+ $('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) {
+ $(e.target).button('toggle')
+ })
+ })
+
+}( window.jQuery )
154 vendor/assets/javascripts/bootstrap-carousel.js
@@ -0,0 +1,154 @@
+/* ==========================================================
+ * bootstrap-carousel.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#carousel
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function( $ ){
+
+ "use strict"
+
+ /* CAROUSEL CLASS DEFINITION
+ * ========================= */
+
+ var Carousel = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.carousel.defaults, options)
+ this.options.slide && this.slide(this.options.slide)
+ }
+
+ Carousel.prototype = {
+
+ cycle: function () {
+ this.interval = setInterval($.proxy(this.next, this), this.options.interval)
+ return this
+ }
+
+ , to: function (pos) {
+ var $active = this.$element.find('.active')
+ , children = $active.parent().children()
+ , activePos = children.index($active)
+ , that = this
+
+ if (pos > (children.length - 1) || pos < 0) return
+
+ if (this.sliding) {
+ return this.$element.one('slid', function () {
+ that.to(pos)
+ })
+ }
+
+ if (activePos == pos) {
+ return this.pause().cycle()
+ }
+
+ return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos]))
+ }
+
+ , pause: function () {
+ clearInterval(this.interval)
+ return this
+ }
+
+ , next: function () {
+ if (this.sliding) return
+ return this.slide('next')
+ }
+
+ , prev: function () {
+ if (this.sliding) return
+ return this.slide('prev')
+ }
+
+ , slide: function (type, next) {
+ var $active = this.$element.find('.active')
+ , $next = next || $active[type]()
+ , isCycling = this.interval
+ , direction = type == 'next' ? 'left' : 'right'
+ , fallback = type == 'next' ? 'first' : 'last'
+ , that = this
+
+ this.sliding = true
+
+ isCycling && this.pause()
+
+ $next = $next.length ? $next : this.$element.find('.item')[fallback]()
+
+ if (!$.support.transition && this.$element.hasClass('slide')) {
+ this.$element.trigger('slide')
+ $active.removeClass('active')
+ $next.addClass('active')
+ this.sliding = false
+ this.$element.trigger('slid')
+ } else {
+ $next.addClass(type)
+ $next[0].offsetWidth // force reflow
+ $active.addClass(direction)
+ $next.addClass(direction)
+ this.$element.trigger('slide')
+ this.$element.one($.support.transition.end, function () {
+ $next.removeClass([type, direction].join(' ')).addClass('active')
+ $active.removeClass(['active', direction].join(' '))
+ that.sliding = false
+ setTimeout(function () { that.$element.trigger('slid') }, 0)
+ })
+ }
+
+ isCycling && this.cycle()
+
+ return this
+ }
+
+ }
+
+
+ /* CAROUSEL PLUGIN DEFINITION
+ * ========================== */
+
+ $.fn.carousel = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('carousel')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('carousel', (data = new Carousel(this, options)))
+ if (typeof option == 'number') data.to(option)
+ else if (typeof option == 'string' || (option = options.slide)) data[option]()
+ else data.cycle()
+ })
+ }
+
+ $.fn.carousel.defaults = {
+ interval: 5000
+ }
+
+ $.fn.carousel.Constructor = Carousel
+
+
+ /* CAROUSEL DATA-API
+ * ================= */
+
+ $(function () {
+ $('body').on('click.carousel.data-api', '[data-slide]', function ( e ) {
+ var $this = $(this), href
+ , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+ , options = !$target.data('modal') && $.extend({}, $target.data(), $this.data())
+ $target.carousel(options)
+ e.preventDefault()
+ })
+ })
+
+}( window.jQuery )
136 vendor/assets/javascripts/bootstrap-collapse.js
@@ -0,0 +1,136 @@
+/* =============================================================
+ * bootstrap-collapse.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#collapse
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+!function( $ ){
+
+ "use strict"
+
+ var Collapse = function ( element, options ) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.collapse.defaults, options)
+
+ if (this.options["parent"]) {
+ this.$parent = $(this.options["parent"])
+ }
+
+ this.options.toggle && this.toggle()
+ }
+
+ Collapse.prototype = {
+
+ constructor: Collapse
+
+ , dimension: function () {
+ var hasWidth = this.$element.hasClass('width')
+ return hasWidth ? 'width' : 'height'
+ }
+
+ , show: function () {
+ var dimension = this.dimension()
+ , scroll = $.camelCase(['scroll', dimension].join('-'))
+ , actives = this.$parent && this.$parent.find('.in')
+ , hasData
+
+ if (actives && actives.length) {
+ hasData = actives.data('collapse')
+ actives.collapse('hide')
+ hasData || actives.data('collapse', null)
+ }
+
+ this.$element[dimension](0)
+ this.transition('addClass', 'show', 'shown')
+ this.$element[dimension](this.$element[0][scroll])
+
+ }
+
+ , hide: function () {
+ var dimension = this.dimension()
+ this.reset(this.$element[dimension]())
+ this.transition('removeClass', 'hide', 'hidden')
+ this.$element[dimension](0)
+ }
+
+ , reset: function ( size ) {
+ var dimension = this.dimension()
+
+ this.$element
+ .removeClass('collapse')
+ [dimension](size || 'auto')
+ [0].offsetWidth
+
+ this.$element.addClass('collapse')
+ }
+
+ , transition: function ( method, startEvent, completeEvent ) {
+ var that = this
+ , complete = function () {
+ if (startEvent == 'show') that.reset()
+ that.$element.trigger(completeEvent)
+ }
+
+ this.$element
+ .trigger(startEvent)
+ [method]('in')
+
+ $.support.transition && this.$element.hasClass('collapse') ?
+ this.$element.one($.support.transition.end, complete) :
+ complete()
+ }
+
+ , toggle: function () {
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
+ }
+
+ }
+
+ /* COLLAPSIBLE PLUGIN DEFINITION
+ * ============================== */
+
+ $.fn.collapse = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('collapse')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('collapse', (data = new Collapse(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.collapse.defaults = {
+ toggle: true
+ }
+
+ $.fn.collapse.Constructor = Collapse
+
+
+ /* COLLAPSIBLE DATA-API
+ * ==================== */
+
+ $(function () {
+ $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) {
+ var $this = $(this), href
+ , target = $this.attr('data-target')
+ || e.preventDefault()
+ || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
+ , option = $(target).data('collapse') ? 'toggle' : $this.data()
+ $(target).collapse(option)
+ })
+ })
+
+}( window.jQuery )
92 vendor/assets/javascripts/bootstrap-dropdown.js
@@ -0,0 +1,92 @@
+/* ============================================================
+ * bootstrap-dropdown.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function( $ ){
+
+ "use strict"
+
+ /* DROPDOWN CLASS DEFINITION
+ * ========================= */
+
+ var toggle = '[data-toggle="dropdown"]'
+ , Dropdown = function ( element ) {
+ var $el = $(element).on('click.dropdown.data-api', this.toggle)
+ $('html').on('click.dropdown.data-api', function () {
+ $el.parent().removeClass('open')
+ })
+ }
+
+ Dropdown.prototype = {
+
+ constructor: Dropdown
+
+ , toggle: function ( e ) {
+ var $this = $(this)
+ , selector = $this.attr('data-target')
+ , $parent
+ , isActive
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ $parent = $(selector)
+ $parent.length || ($parent = $this.parent())
+
+ isActive = $parent.hasClass('open')
+
+ clearMenus()
+ !isActive && $parent.toggleClass('open')
+
+ return false
+ }
+
+ }
+
+ function clearMenus() {
+ $(toggle).parent().removeClass('open')
+ }
+
+
+ /* DROPDOWN PLUGIN DEFINITION
+ * ========================== */
+
+ $.fn.dropdown = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('dropdown')
+ if (!data) $this.data('dropdown', (data = new Dropdown(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ $.fn.dropdown.Constructor = Dropdown
+
+
+ /* APPLY TO STANDARD DROPDOWN ELEMENTS
+ * =================================== */
+
+ $(function () {
+ $('html').on('click.dropdown.data-api', clearMenus)
+ $('body').on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle)
+ })
+
+}( window.jQuery )
210 vendor/assets/javascripts/bootstrap-modal.js
@@ -0,0 +1,210 @@
+/* =========================================================
+ * bootstrap-modal.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#modals
+ * =========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+
+!function( $ ){
+
+ "use strict"
+
+ /* MODAL CLASS DEFINITION
+ * ====================== */
+
+ var Modal = function ( content, options ) {
+ this.options = options
+ this.$element = $(content)
+ .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
+ }
+
+ Modal.prototype = {
+
+ constructor: Modal
+
+ , toggle: function () {
+ return this[!this.isShown ? 'show' : 'hide']()
+ }
+
+ , show: function () {
+ var that = this
+
+ if (this.isShown) return
+
+ $('body').addClass('modal-open')
+
+ this.isShown = true
+ this.$element.trigger('show')
+
+ escape.call(this)
+ backdrop.call(this, function () {
+ var transition = $.support.transition && that.$element.hasClass('fade')
+
+ !that.$element.parent().length && that.$element.appendTo(document.body) //don't move modals dom position
+
+ that.$element
+ .show()
+
+ if (transition) {
+ that.$element[0].offsetWidth // force reflow
+ }
+
+ that.$element.addClass('in')
+
+ transition ?
+ that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
+ that.$element.trigger('shown')
+
+ })
+ }
+
+ , hide: function ( e ) {
+ e && e.preventDefault()
+
+ if (!this.isShown) return
+
+ var that = this
+ this.isShown = false
+
+ $('body').removeClass('modal-open')
+
+ escape.call(this)
+
+ this.$element
+ .trigger('hide')
+ .removeClass('in')
+
+ $.support.transition && this.$element.hasClass('fade') ?
+ hideWithTransition.call(this) :
+ hideModal.call(this)
+ }
+
+ }
+
+
+ /* MODAL PRIVATE METHODS
+ * ===================== */
+
+ function hideWithTransition() {
+ var that = this
+ , timeout = setTimeout(function () {
+ that.$element.off($.support.transition.end)
+ hideModal.call(that)
+ }, 500)
+
+ this.$element.one($.support.transition.end, function () {
+ clearTimeout(timeout)
+ hideModal.call(that)
+ })
+ }
+
+ function hideModal( that ) {
+ this.$element
+ .hide()
+ .trigger('hidden')
+
+ backdrop.call(this)
+ }
+
+ function backdrop( callback ) {
+ var that = this
+ , animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+ if (this.isShown && this.options.backdrop) {
+ var doAnimate = $.support.transition && animate
+
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+ .appendTo(document.body)
+
+ if (this.options.backdrop != 'static') {
+ this.$backdrop.click($.proxy(this.hide, this))
+ }
+
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+ this.$backdrop.addClass('in')
+
+ doAnimate ?
+ this.$backdrop.one($.support.transition.end, callback) :
+ callback()
+
+ } else if (!this.isShown && this.$backdrop) {
+ this.$backdrop.removeClass('in')
+
+ $.support.transition && this.$element.hasClass('fade')?
+ this.$backdrop.one($.support.transition.end, $.proxy(removeBackdrop, this)) :
+ removeBackdrop.call(this)
+
+ } else if (callback) {
+ callback()
+ }
+ }
+
+ function removeBackdrop() {
+ this.$backdrop.remove()
+ this.$backdrop = null
+ }
+
+ function escape() {
+ var that = this
+ if (this.isShown && this.options.keyboard) {
+ $(document).on('keyup.dismiss.modal', function ( e ) {
+ e.which == 27 && that.hide()
+ })
+ } else if (!this.isShown) {
+ $(document).off('keyup.dismiss.modal')
+ }
+ }
+
+
+ /* MODAL PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.modal = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('modal')
+ , options = $.extend({}, $.fn.modal.defaults, typeof option == 'object' && option)
+ if (!data) $this.data('modal', (data = new Modal(this, options)))
+ if (typeof option == 'string') data[option]()
+ else if (options.show) data.show()
+ })
+ }
+
+ $.fn.modal.defaults = {
+ backdrop: true
+ , keyboard: true
+ , show: true
+ }
+
+ $.fn.modal.Constructor = Modal
+
+
+ /* MODAL DATA-API
+ * ============== */
+
+ $(function () {
+ $('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
+ var $this = $(this), href
+ , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+ , option = $target.data('modal') ? 'toggle' : $.extend({}, $target.data(), $this.data())
+
+ e.preventDefault()
+ $target.modal(option)
+ })
+ })
+
+}( window.jQuery )
95 vendor/assets/javascripts/bootstrap-popover.js
@@ -0,0 +1,95 @@
+/* ===========================================================
+ * bootstrap-popover.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================================================== */
+
+
+!function( $ ) {
+
+ "use strict"
+
+ var Popover = function ( element, options ) {
+ this.init('popover', element, options)
+ }
+
+ /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
+ ========================================== */
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
+
+ constructor: Popover
+