Recipe Editor
This commit is contained in:
parent
3b4134f684
commit
0388d428a6
@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
||||
|
||||
@mixin editor {
|
||||
@extend .panel-body;
|
||||
}
|
||||
|
||||
div.ingredient-editor {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
<%= render 'form' %>
|
||||
|
||||
<%= link_to 'Show', @ingredient, class: 'btn btn-primary' %> |
|
||||
<%= link_to 'Back', ingredients_path, class: 'btn btn-primary' %>
|
||||
|
||||
</div>
|
||||
|
@ -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 %>
|
||||
|
@ -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>
|
@ -1 +0,0 @@
|
||||
json.extract! @ingredient, :id, :created_at, :updated_at
|
@ -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>
|
@ -19,7 +19,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= f.hidden_field :sort_order, class: 'sort-order' %>
|
||||
<%= f.hidden_field :sort_order, class: 'sort_order' %>
|
||||
|
||||
</div>
|
||||
</div>
|
@ -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
|
||||
|
@ -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'},
|
||||
|
Loading…
Reference in New Issue
Block a user