Recipe Editor

This commit is contained in:
Dan Elbert 2016-01-14 18:56:45 -06:00
parent 3b4134f684
commit 0388d428a6
12 changed files with 98 additions and 43 deletions

View File

@ -1,25 +1,72 @@
(function($) {
function reorder($container) {
console.log($container);
$container.find("div.nested-fields").each(function(idx, editor) {
var $editor = $(editor);
$editor.find('input.sort-order').val(idx + 1).trigger("changed");
$editor.find('input.sort_order').val(idx + 1).trigger("changed");
})
}
function initializeIngredientEditor($container, ingredientSearchEngine) {
$container.find(".ingredient-typeahead").typeahead({
// $container is either an element that contains many editors, or a single editor.
var $editors = $container.find(".ingredient-typeahead").closest(".nested-fields");
},
{
name: 'ingredients',
source: ingredientSearchEngine,
display: function(datum) {
return datum.name;
$editors.each(function(idx, elem) {
var $editor = $(elem);
var $ingredientId = $editor.find("input.ingredient_id");
var $customDensity = $editor.find("input.custom_density");
var $group = $editor.find("div.typeahead-group");
$editor.find(".ingredient-typeahead").typeahead({},
{
name: 'ingredients',
source: ingredientSearchEngine,
display: function(datum) {
return datum.name;
}
});
if ($ingredientId.val().length) {
$customDensity.prop('disabled', true);
$group.addClass("has-success");
}
});
}
function ingredientItemPicked($typeahead, datum) {
var $container = $typeahead.closest(".nested-fields");
var $ingredientId = $container.find("input.ingredient_id");
var $customDensity = $container.find("input.custom_density");
var $group = $container.find("div.typeahead-group");
$ingredientId.val(datum.id);
$typeahead.typeahead('val', datum.name);
$customDensity.val(datum.density).prop('disabled', true);
$group.addClass("has-success");
}
function ingredientNameChange($typeahead, ingredientSearchEngine) {
var $container = $typeahead.closest(".nested-fields");
var $ingredientId = $container.find("input.ingredient_id");
var $customDensity = $container.find("input.custom_density");
var $group = $container.find("div.typeahead-group");
var id = $ingredientId.val();
var value = $typeahead.typeahead('val');
if (id && id.length) {
var found = ingredientSearchEngine.get([id]);
if (found && found[0] && found[0].name != value) {
// User has chosen something custom
$ingredientId.val('');
$customDensity.val('').prop('disabled', false);
$group.removeClass("has-success");
}
}
}
$(document).on("ready page:load", function() {
var ingredientSearchEngine = new Bloodhound({
@ -66,11 +113,23 @@
$ingredientList
.on("cocoon:after-insert", function(e, item) {
reorder($(this));
reorder($ingredientList);
initializeIngredientEditor(item, ingredientSearchEngine);
})
.on("cocoon:after-remove", function(e, item) {
reorder($(this));
reorder($ingredientList);
})
.on("typeahead:change", function(evt, value) {
console.log("changed");
ingredientNameChange($(evt.target), ingredientSearchEngine);
})
.on("typeahead:select", function(evt, value) {
console.log("selected");
ingredientItemPicked($(evt.target), value);
})
.on("typeahead:autocomplete", function(evt, value) {
console.log("autocomplete");
ingredientItemPicked($(evt.target), value);
});
});

View File

@ -3,7 +3,6 @@
// You can use Sass (SCSS) here: http://sass-lang.com/
@mixin editor {
@extend .panel-body;
}
div.ingredient-editor {

View File

@ -1,5 +1,5 @@
class IngredientsController < ApplicationController
before_action :set_ingredient, only: [:show, :edit, :update, :destroy]
before_action :set_ingredient, only: [:edit, :update, :destroy]
# GET /ingredients
# GET /ingredients.json
@ -7,11 +7,6 @@ class IngredientsController < ApplicationController
@ingredients = Ingredient.all.order(:name)
end
# GET /ingredients/1
# GET /ingredients/1.json
def show
end
# GET /ingredients/new
def new
@ingredient = Ingredient.new

View File

@ -6,4 +6,20 @@ class RecipeIngredient < ActiveRecord::Base
validates :sort_order, presence: true
validates :custom_density, density: true, allow_blank: true
def custom_name
if self.ingredient_id.present?
self.ingredient.name
else
super
end
end
def custom_density
if self.ingredient_id.present?
self.ingredient.density
else
super
end
end
end

View File

@ -5,7 +5,6 @@
<%= render 'form' %>
<%= link_to 'Show', @ingredient, class: 'btn btn-primary' %> |
<%= link_to 'Back', ingredients_path, class: 'btn btn-primary' %>
</div>

View File

@ -16,10 +16,8 @@
<tbody>
<% @ingredients.each do |ingredient| %>
<tr>
<td><%= ingredient.name %></td>
<td><%= link_to ingredient.name, edit_ingredient_path(ingredient) %></td>
<td><%= ingredient.density %></td>
<td><%= link_to 'Show', ingredient %></td>
<td><%= link_to 'Edit', edit_ingredient_path(ingredient) %></td>
<td><%= link_to 'Destroy', ingredient, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>

View File

@ -1,13 +0,0 @@
<div class="row">
<div class="col-xs-12">
<h3><%= @ingredient.name %></h3>
<p><%= @ingredient.notes %></p>
<%= link_to 'Edit', edit_ingredient_path(@ingredient), class: 'btn btn-default' %>
<%= link_to 'Back', ingredients_path, class: 'btn btn-default' %>
</div>
</div>

View File

@ -1 +0,0 @@
json.extract! @ingredient, :id, :created_at, :updated_at

View File

@ -1,12 +1,12 @@
<div class="panel panel-default">
<div class="nested-fields ingredient-editor">
<div class="panel panel-default nested-fields ingredient-editor">
<div class="panel-body">
<div class="row">
<div class="col-xs-10">
<div class="form-group form-group-sm">
<div class="form-group form-group-sm typeahead-group">
<%= f.label :custom_name, "Name" %>
<%= f.text_field :custom_name, class: 'form-control ingredient-typeahead' %>
<%= f.text_field :custom_name, class: 'form-control ingredient-typeahead custom_name' %>
</div>
<div class="row">
@ -27,7 +27,7 @@
<div class="col-xs-4">
<div class="form-group form-group-sm">
<%= f.label :custom_density, "Density" %>
<%= f.text_field :custom_density, class: 'form-control' %>
<%= f.text_field :custom_density, class: 'form-control custom_density' %>
</div>
</div>
</div>
@ -40,6 +40,7 @@
</div>
</div>
<%= f.hidden_field :sort_order, class: 'sort-order' %>
<%= f.hidden_field :ingredient_id, class: 'ingredient_id' %>
<%= f.hidden_field :sort_order, class: 'sort_order' %>
</div>
</div>

View File

@ -19,7 +19,7 @@
</div>
</div>
<%= f.hidden_field :sort_order, class: 'sort-order' %>
<%= f.hidden_field :sort_order, class: 'sort_order' %>
</div>
</div>

View File

@ -1,7 +1,8 @@
Rails.application.routes.draw do
resources :recipes
resources :ingredients do
resources :ingredients, except: [:show] do
collection do
constraints format: 'json' do
get :search

View File

@ -10,6 +10,7 @@
puts "Seeding..."
Ingredient.create!([
{name: 'Water', density: '1 g/ml'},
{name: 'Butter, Salted', density: '226 gram/cup'},
{name: 'Butter, Unsalted', density: '226 gram/cup'},
{name: 'Flour, Bleached All Purpose', density: '130 gram/cup'},