Skip to content

Instantly share code, notes, and snippets.

@jodyheavener
Created January 7, 2015 17:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jodyheavener/568e51d0d8c79fddea68 to your computer and use it in GitHub Desktop.
Save jodyheavener/568e51d0d8c79fddea68 to your computer and use it in GitHub Desktop.
My Dream Cars 2
doctype 5
head
meta charset="utf-8"
meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"
meta name="viewport" content="width=device-width"
title My Dream Cars
link rel="stylesheet" href="styles/site.css"
script src="scripts/jquery.js"
body
.container
h1 What are your dream cars?
.choose-cars
select title="Choose a Dream Car"
input type="submit" value="Add it"
ul.cars-list
script src="scripts/site.js"
# Array of Dream Car objects
dreamCars = [
{ make: "Aston Martin", model: "DB9" }
{ make: "Lotus", model: "Elise" }
{ make: "Maserati", model: "Quattroporte" }
{ make: "Porsche", model: "Panamera" }
{ make: "Aston Martin", model: "Vanquish" }
{ make: "Maserati", model: "GranTurismo" }
{ make: "Maserati", model: "GranCabrio" }
{ make: "Lotus", model: "Exige" }
{ make: "Aston Martin", model: "Vantage" }
{ make: "Porsche", model: "911" }
{ make: "Bugatti", model: "Veyron" }
{ make: "Bugatti", model: "Galibier" }
{ make: "Lotus", model: "Evora" }
{ make: "Lotus", model: "2-eleven" }
]
class window.HarvestTest
$ = jQuery
constructor: ->
container = $(".container")
@carSelect = container.find("select")
@carChoose = container.find("input[type=\"submit\"]")
@carsList = container.find(".cars-list")
# Sort the cars once so we can reference it later
@sortedCars = @sortArrayOfCars(dreamCars)
@createInitialSelections()
@carChoose.on "click", =>
@listCarFromSelection @carSelect.find(":selected")
$(document.body).on "click", ".remove", (event) =>
@restoreCarSelection $(event.target).closest(".car")
sortArrayOfCars: (arrayToSort) ->
cars = {}
# First, group models within the array of objects by make
i = 0
while i < arrayToSort.length
car = arrayToSort[i]
cars[car.make] = [] unless cars[car.make]
cars[car.make].push car.model
i = i + 1
# Then, sort each array of models (by make) alphabetically
# Ideally I'd like to create the array alphabetically in the first place instead of
# creating it and then having to reiterate through again and sort, but ¯\_(ツ)_/¯
for make of cars
cars[make] = cars[make].sort (a, b) ->
return a.localeCompare(b)
return cars
createInitialSelections: ->
groupElement = $("<optgroup />")
optionElement = $("<option />")
for make of @sortedCars
models = @sortedCars[make]
grouper = groupElement.clone().attr("label", make)
i = 0
while i < models.length
model = models[i]
grouper.append optionElement.clone().text(model)
i = i + 1
@carSelect.append grouper
listCarFromSelection: (option) ->
optionGroup = option.parent()
newCar = $("<li class=\"car hidden\" />")
.html("<span><b>#{option.text()}</b> <i>#{optionGroup.attr("label")}</i></span><button class=\"remove\">X</button>")
.prependTo(@carsList)
window.getComputedStyle(newCar[0]).opacity # Access a prop value to flush pending style changes
newCar.removeClass "hidden" # Doing this allows us to apply a transition
siblings = option.siblings()
option.remove()
if siblings.length is 0
optionGroup.remove()
else
@carSelect.val siblings[0].value
if @carSelect.children().length is 0
@listEmpty = yes
@carSelect.html("<option disabled=\"disabled\">Dream big, my friend...</option>")
@carChoose.attr("disabled", "disabled").val("Nope!")
restoreCarSelection: (item) ->
make = item.find("i").text()
model = item.find("b").text()
item.addClass("hidden").on "transitionend", ->
item.remove()
if @listEmpty
@carSelect.html("")
@carChoose.removeAttr("disabled").val("Add it")
@listEmpty = no
optionGroup = @carSelect.find("optgroup[label=\"#{make}\"]")
unless optionGroup.length
return @carSelect.append("<optgroup label=\"#{make}\"><option>#{model}</option></optgroup>")
newOption = "<option>#{model}</option>"
position = @sortedCars[make].indexOf model
siblings = optionGroup.find("option")
# Find the car's alphabetical position within its make
i = 0
while i < siblings.length
sibling = siblings[i]
siblingPosition = @sortedCars[make].indexOf sibling.text
if position < siblingPosition
return $(sibling).before(newOption)
if (i + 1) is siblings.length
return $(sibling).after(newOption)
i = i + 1
new HarvestTest
@import "compass/css3";
@import "normalize";
@import "mixins";
body {
font-family: "Avenir Next", "Avenir", "Helvetica Neue", helvetica, sans-serif;
font-weight: 500;
color: #222;
background: #f4f4f4;
}
.container {
width: 560px;
margin: 100px auto 50px;
box-sizing: border-box;
background-color: #fcfcfc;
box-shadow: 0 2px 4px 0 rgba(0,0,0,.24)
, 0 0 4px 0 rgba(0,0,0,.12);
}
h1 {
margin: 0;
padding-top: 30px;
font-size: 20px;
font-weight: 600;
color: #444;
text-align: center;
}
.choose-cars {
padding: 30px;
text-align: center;
select {
height: 40px;
width: 390px;
background: #fff;
border: 1px solid #C3C3C3;
font-size: 14px;
&:focus {
outline: none;
border: 1px solid #999;
box-shadow: 0 0 0 2px #ddd;
}
}
input[type="submit"] {
margin-left: 15px;
padding: 10px 18px;
background: #009688;
border: none;
border-radius: 4px;
color: #fff;
font-size: 14px;
font-weight: 700;
text-transform: uppercase;
-webkit-font-smoothing: antialiased;
@include transition(all 0.1s ease-in);
&:hover {
background-color: #008074;
box-shadow: 0 10px 20px rgba(0,0,0,.13)
, 0 4px 7px rgba(0,0,0,.2);
}
&:active {
transform: translateY(1px);
}
&:focus {
outline: none;
}
&:disabled,
&:disabled:hover {
background: #DBDBDB;
color: #FCFCFC;
box-shadow: none;
}
}
}
.cars-list {
margin: 0 auto;
padding: 0;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
list-style-type: none;
list-style-position: inside;
&:empty {
display: none;
}
li {
@extend %clearfix;
background: #f8f8f8;
font-size: 17px;
border-top: 1px solid #efefef;
color: #6E6E6E;
cursor: default;
max-height: 80px;
overflow: hidden;
@include transition(all .23s cubic-bezier(.55,0,.1,1));
&:hover {
background: #F5F5F5;
}
&.hidden {
max-height: 0;
}
}
.remove {
margin: 25px 30px 14px;
padding: 5px 8px 4px;
background: #EAEAEA;
border: none;
border-radius: 50%;
font-size: 11px;
font-weight: 600;
color: #868686;
float: right;
@include transition(all 0.1s ease-in);
&:hover {
background-color: #009688;
color: #fff;
}
&:focus {
outline: none;
}
}
span {
margin: 27px 30px 24px;
display: block;
float: left;
}
b {
font-weight: 600;
}
i {
position: relative;
top: -1px;
margin-left: 7px;
font-style: normal;
font-size: 14px;
text-transform: uppercase;
font-weight: 600;
color: #A0A0A0;
letter-spacing: 1px;
-webkit-font-smoothing: antialiased;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment