UI updates
This commit is contained in:
parent
205a29ce77
commit
0cc568344e
36
app/assets/javascripts/checkable.js
Normal file
36
app/assets/javascripts/checkable.js
Normal file
@ -0,0 +1,36 @@
|
||||
(function($) {
|
||||
|
||||
var pluginName = "checkable";
|
||||
|
||||
var defaultOptions = {
|
||||
childrenSelector: "li",
|
||||
selectedClass: "checked"
|
||||
};
|
||||
|
||||
var methods = {
|
||||
initialize: function (opts, sources) {
|
||||
|
||||
return this.each(function() {
|
||||
var options = $.extend({}, defaultOptions, opts);
|
||||
$(this).on("click", options.childrenSelector, function(evt) {
|
||||
$(evt.currentTarget).toggleClass(options.selectedClass);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var privateMethods = {
|
||||
|
||||
};
|
||||
|
||||
$.fn[pluginName] = function (method) {
|
||||
if (methods[method]) {
|
||||
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
|
||||
} else if (typeof method === 'object' || ! method) {
|
||||
return methods.initialize.apply(this, arguments);
|
||||
} else {
|
||||
$.error('Method ' + method + ' does not exist on jQuery.' + pluginName);
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
375
app/assets/javascripts/recipe_editor.js
Normal file
375
app/assets/javascripts/recipe_editor.js
Normal file
@ -0,0 +1,375 @@
|
||||
(function($) {
|
||||
|
||||
var ingredientSearchEngine = new Bloodhound({
|
||||
initialize: false,
|
||||
datumTokenizer: function(datum) {
|
||||
return Bloodhound.tokenizers.whitespace(datum.name);
|
||||
},
|
||||
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
||||
identify: function(datum) { return datum.id; },
|
||||
sorter: function(a, b) {
|
||||
if (a.name < b.name) {
|
||||
return -1;
|
||||
} else if (b.name < a.name) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
prefetch: {
|
||||
url: '/ingredients/prefetch.json',
|
||||
cache: false
|
||||
},
|
||||
remote: {
|
||||
url: '/ingredients/search.json?query=%QUERY',
|
||||
wildcard: '%QUERY'
|
||||
}
|
||||
});
|
||||
|
||||
function reorder($container) {
|
||||
$container.find("div.nested-fields").each(function(idx, editor) {
|
||||
var $editor = $(editor);
|
||||
$editor.find('input.sort_order').val(idx + 1).trigger("changed");
|
||||
})
|
||||
}
|
||||
|
||||
function initializeStepEditor($container) {
|
||||
// $container is either an element that contains many editors, or a single editor.
|
||||
var $editors = $container.find("textarea.step").closest(".step-editor");
|
||||
|
||||
$editors.each(function(idx, elem) {
|
||||
var $editor = $(elem);
|
||||
var $step = $editor.find("textarea.step");
|
||||
autosize($step);
|
||||
|
||||
setTimeout(function() { autosize.update($step); }, 250);
|
||||
});
|
||||
}
|
||||
|
||||
function initializeIngredientEditor($container, ingredientSearchEngine) {
|
||||
// $container is either an element that contains many editors, or a single editor.
|
||||
var $editors = $container.find(".ingredient-typeahead").closest(".nested-fields");
|
||||
|
||||
$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 $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('');
|
||||
|
||||
$group.removeClass("has-success");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addIngredient(quantity, units, name, ingredient_id) {
|
||||
$("#ingredient-list").one("cocoon:before-insert", function(e, $container) {
|
||||
var $ingredientId = $container.find("input.ingredient_id");
|
||||
var $name = $container.find("input.custom_name");
|
||||
var $quantity = $container.find("input.quantity");
|
||||
var $units = $container.find("input.units");
|
||||
|
||||
$ingredientId.typeahead("val", name);
|
||||
$name.val(name);
|
||||
$units.val(units);
|
||||
$quantity.val(quantity);
|
||||
});
|
||||
|
||||
$("#addIngredientButton").trigger("click");
|
||||
}
|
||||
|
||||
function addStep(step) {
|
||||
$("#step-list").one("cocoon:before-insert", function(e, $container) {
|
||||
var $step = $container.find("textarea.step");
|
||||
$step.val(step);
|
||||
});
|
||||
|
||||
$("#addStepButton").trigger("click");
|
||||
}
|
||||
|
||||
$(document).on("ready page:load", function() {
|
||||
|
||||
var $ingredientList = $("#ingredient-list");
|
||||
var $stepList = $("#step-list");
|
||||
|
||||
if ($ingredientList.length) {
|
||||
ingredientSearchEngine.initialize(false);
|
||||
}
|
||||
|
||||
initializeStepEditor($stepList);
|
||||
|
||||
$stepList
|
||||
.on("cocoon:after-insert", function(e, item) {
|
||||
reorder($(this));
|
||||
initializeStepEditor(item);
|
||||
})
|
||||
.on("cocoon:after-remove", function(e, item) {
|
||||
reorder($(this));
|
||||
})
|
||||
.on('changed', 'input.sort_order', function() {
|
||||
var $this = $(this);
|
||||
var $span = $this.closest(".nested-fields").find(".sort-order-display");
|
||||
$span.html($this.val());
|
||||
});
|
||||
|
||||
|
||||
initializeIngredientEditor($ingredientList, ingredientSearchEngine);
|
||||
|
||||
$ingredientList
|
||||
.on("cocoon:after-insert", function(e, item) {
|
||||
reorder($ingredientList);
|
||||
initializeIngredientEditor(item, ingredientSearchEngine);
|
||||
})
|
||||
.on("cocoon:after-remove", function(e, item) {
|
||||
reorder($ingredientList);
|
||||
})
|
||||
.on("typeahead:change", function(evt, value) {
|
||||
ingredientNameChange($(evt.target), ingredientSearchEngine);
|
||||
})
|
||||
.on("typeahead:select", function(evt, value) {
|
||||
ingredientItemPicked($(evt.target), value);
|
||||
})
|
||||
.on("typeahead:autocomplete", function(evt, value) {
|
||||
ingredientItemPicked($(evt.target), value);
|
||||
})
|
||||
.on("click", "button.ingredient_convert_btn", function(evt) {
|
||||
|
||||
});
|
||||
|
||||
$('#convert_modal')
|
||||
.on('show.bs.modal', function (event) {
|
||||
var $button = $(event.relatedTarget);
|
||||
var $modal = $(this);
|
||||
|
||||
var $editor = $button.closest(".ingredient-editor");
|
||||
|
||||
$modal.data('ingredient-editor', $editor);
|
||||
|
||||
var $quantity = $editor.find("input.quantity");
|
||||
var $units = $editor.find("input.units");
|
||||
var $ingredientId = $editor.find("input.ingredient_id");
|
||||
|
||||
var $modalQuantity = $modal.find("input.quantity");
|
||||
var $modalUnits = $modal.find("input.units");
|
||||
var $modalIngredientId = $modal.find("input.ingredient_id");
|
||||
|
||||
$modalQuantity.val($quantity.val());
|
||||
$modalUnits.val($units.val());
|
||||
$modalIngredientId.val($ingredientId.val());
|
||||
})
|
||||
.on("ajax:success", "form", function(evt, data, status, xhr) {
|
||||
var $modal = $("#convert_modal");
|
||||
var $editor = $modal.data('ingredient-editor');
|
||||
|
||||
if (data.success) {
|
||||
var $quantity = $editor.find("input.quantity");
|
||||
var $units = $editor.find("input.units");
|
||||
|
||||
var $modalOutUnits = $modal.find("input.output_units");
|
||||
|
||||
$quantity.val(data.output_quantity);
|
||||
if ($modalOutUnits.val().length) {
|
||||
$units.val($modalOutUnits.val());
|
||||
}
|
||||
|
||||
$modal.modal('hide');
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
$("#modal_form_container").replaceWith($(data.form_html));
|
||||
});
|
||||
|
||||
var $bulkIngredientsModal = $("#bulk_ingredients_modal");
|
||||
var $ingredientBulkInput = $("#ingredient_bulk_input");
|
||||
var $ingredientBulkList = $("#ingredient_bulk_parsed_list");
|
||||
autosize($ingredientBulkInput);
|
||||
|
||||
$bulkIngredientsModal
|
||||
.on('show.bs.modal', function (event) {
|
||||
$ingredientBulkInput.val('');
|
||||
$ingredientBulkList.empty();
|
||||
autosize.update($ingredientBulkInput);
|
||||
});
|
||||
|
||||
$ingredientBulkInput.on('keyup', function() {
|
||||
var data = $ingredientBulkInput.val();
|
||||
$ingredientBulkList.empty();
|
||||
|
||||
var parsed = [];
|
||||
var x;
|
||||
|
||||
var lines = data.replace("\r", "").split("\n");
|
||||
|
||||
var regex = /^(?:([\d\/.]+(?:\s+[\d\/]+)?)\s+)?(?:([\w-]+)(?:\s+of)?\s+)?(\w[\w ,\-\(\)\/'"]*)$/i;
|
||||
|
||||
var magicFunc = function(str) {
|
||||
if (str == "-") {
|
||||
return "";
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
for (x = 0; x < lines.length; x++) {
|
||||
var line = lines[x].trim();
|
||||
if (line.length == 0) { continue; }
|
||||
|
||||
var match = line.match(regex);
|
||||
|
||||
if (match) {
|
||||
parsed.push({quantity: magicFunc(match[1]), units: magicFunc(match[2]), name: magicFunc(match[3])});
|
||||
} else {
|
||||
parsed.push(null);
|
||||
}
|
||||
}
|
||||
|
||||
$bulkIngredientsModal.data("bulkData", parsed);
|
||||
|
||||
for (x = 0; x < parsed.length; x++) {
|
||||
var item = parsed[x];
|
||||
if (item != null) {
|
||||
$ingredientBulkList.append(
|
||||
$("<tr />")
|
||||
.append($("<td />").addClass("quantity").text(item.quantity))
|
||||
.append($("<td />").addClass("units").text(item.units))
|
||||
.append($("<td />").addClass("name").text(item.name))
|
||||
);
|
||||
} else {
|
||||
$ingredientBulkList.append(
|
||||
$("<tr />")
|
||||
.append($("<td />").attr("colspan", "3").text("<Cannot Parse>"))
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#bulkIngredientAddSubmit").on("click", function() {
|
||||
var parsed = $bulkIngredientsModal.data("bulkData");
|
||||
var x;
|
||||
|
||||
if (parsed && parsed.length) {
|
||||
for (x = 0; x < parsed.length; x++) {
|
||||
var item = parsed[x];
|
||||
if (item) {
|
||||
addIngredient(item.quantity, item.units, item.name, item.ingredient_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$bulkIngredientsModal.modal('hide')
|
||||
});
|
||||
|
||||
|
||||
// ===========================================
|
||||
// ===========================================
|
||||
|
||||
|
||||
var $bulkStepsModal = $("#bulk_steps_modal");
|
||||
var $stepBulkInput = $("#step_bulk_input");
|
||||
var $stepBulkList = $("#step_bulk_parsed_list");
|
||||
autosize($stepBulkInput);
|
||||
|
||||
$bulkStepsModal
|
||||
.on('show.bs.modal', function (event) {
|
||||
$stepBulkInput.val('');
|
||||
$stepBulkList.empty();
|
||||
autosize.update($stepBulkInput);
|
||||
});
|
||||
|
||||
$stepBulkInput.on('keyup', function() {
|
||||
var data = $stepBulkInput.val();
|
||||
$stepBulkList.empty();
|
||||
|
||||
var parsed = [];
|
||||
var x;
|
||||
|
||||
var lines = data.replace("\r", "").split("\n\n");
|
||||
|
||||
for (x = 0; x < lines.length; x++) {
|
||||
var line = lines[x].trim().replace(/^\d+\./, "").trim();
|
||||
if (line.length == 0) { continue; }
|
||||
|
||||
parsed.push(line);
|
||||
}
|
||||
|
||||
$bulkStepsModal.data("bulkData", parsed);
|
||||
|
||||
for (x = 0; x < parsed.length; x++) {
|
||||
var item = parsed[x];
|
||||
if (item != null) {
|
||||
$stepBulkList.append(
|
||||
$("<tr />")
|
||||
.append($("<td />").addClass("step").text(x + 1))
|
||||
.append($("<td />").addClass("direction").text(item))
|
||||
);
|
||||
} else {
|
||||
$stepBulkList.append(
|
||||
$("<tr />")
|
||||
.append($("<td />").attr("colspan", "2").text("<Cannot Parse>"))
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#bulkStepAddSubmit").on("click", function() {
|
||||
var parsed = $bulkStepsModal.data("bulkData");
|
||||
var x;
|
||||
|
||||
if (parsed && parsed.length) {
|
||||
for (x = 0; x < parsed.length; x++) {
|
||||
var item = parsed[x];
|
||||
if (item) {
|
||||
addStep(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$bulkStepsModal.modal('hide')
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
})(jQuery);
|
@ -1,375 +1,8 @@
|
||||
(function($) {
|
||||
|
||||
var ingredientSearchEngine = new Bloodhound({
|
||||
initialize: false,
|
||||
datumTokenizer: function(datum) {
|
||||
return Bloodhound.tokenizers.whitespace(datum.name);
|
||||
},
|
||||
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
||||
identify: function(datum) { return datum.id; },
|
||||
sorter: function(a, b) {
|
||||
if (a.name < b.name) {
|
||||
return -1;
|
||||
} else if (b.name < a.name) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
prefetch: {
|
||||
url: '/ingredients/prefetch.json',
|
||||
cache: false
|
||||
},
|
||||
remote: {
|
||||
url: '/ingredients/search.json?query=%QUERY',
|
||||
wildcard: '%QUERY'
|
||||
}
|
||||
});
|
||||
|
||||
function reorder($container) {
|
||||
$container.find("div.nested-fields").each(function(idx, editor) {
|
||||
var $editor = $(editor);
|
||||
$editor.find('input.sort_order').val(idx + 1).trigger("changed");
|
||||
})
|
||||
}
|
||||
|
||||
function initializeStepEditor($container) {
|
||||
// $container is either an element that contains many editors, or a single editor.
|
||||
var $editors = $container.find("textarea.step").closest(".step-editor");
|
||||
|
||||
$editors.each(function(idx, elem) {
|
||||
var $editor = $(elem);
|
||||
var $step = $editor.find("textarea.step");
|
||||
autosize($step);
|
||||
|
||||
setTimeout(function() { autosize.update($step); }, 250);
|
||||
});
|
||||
}
|
||||
|
||||
function initializeIngredientEditor($container, ingredientSearchEngine) {
|
||||
// $container is either an element that contains many editors, or a single editor.
|
||||
var $editors = $container.find(".ingredient-typeahead").closest(".nested-fields");
|
||||
|
||||
$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 $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('');
|
||||
|
||||
$group.removeClass("has-success");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addIngredient(quantity, units, name, ingredient_id) {
|
||||
$("#ingredient-list").one("cocoon:before-insert", function(e, $container) {
|
||||
var $ingredientId = $container.find("input.ingredient_id");
|
||||
var $name = $container.find("input.custom_name");
|
||||
var $quantity = $container.find("input.quantity");
|
||||
var $units = $container.find("input.units");
|
||||
|
||||
$ingredientId.typeahead("val", name);
|
||||
$name.val(name);
|
||||
$units.val(units);
|
||||
$quantity.val(quantity);
|
||||
});
|
||||
|
||||
$("#addIngredientButton").trigger("click");
|
||||
}
|
||||
|
||||
function addStep(step) {
|
||||
$("#step-list").one("cocoon:before-insert", function(e, $container) {
|
||||
var $step = $container.find("textarea.step");
|
||||
$step.val(step);
|
||||
});
|
||||
|
||||
$("#addStepButton").trigger("click");
|
||||
}
|
||||
|
||||
$(document).on("ready page:load", function() {
|
||||
|
||||
var $ingredientList = $("#ingredient-list");
|
||||
var $stepList = $("#step-list");
|
||||
|
||||
if ($ingredientList.length) {
|
||||
ingredientSearchEngine.initialize(false);
|
||||
}
|
||||
|
||||
initializeStepEditor($stepList);
|
||||
|
||||
$stepList
|
||||
.on("cocoon:after-insert", function(e, item) {
|
||||
reorder($(this));
|
||||
initializeStepEditor(item);
|
||||
})
|
||||
.on("cocoon:after-remove", function(e, item) {
|
||||
reorder($(this));
|
||||
})
|
||||
.on('changed', 'input.sort_order', function() {
|
||||
var $this = $(this);
|
||||
var $span = $this.closest(".nested-fields").find(".sort-order-display");
|
||||
$span.html($this.val());
|
||||
$(".recipe-view ul.ingredients").checkable();
|
||||
$(".recipe-view ol.steps").checkable();
|
||||
});
|
||||
|
||||
|
||||
initializeIngredientEditor($ingredientList, ingredientSearchEngine);
|
||||
|
||||
$ingredientList
|
||||
.on("cocoon:after-insert", function(e, item) {
|
||||
reorder($ingredientList);
|
||||
initializeIngredientEditor(item, ingredientSearchEngine);
|
||||
})
|
||||
.on("cocoon:after-remove", function(e, item) {
|
||||
reorder($ingredientList);
|
||||
})
|
||||
.on("typeahead:change", function(evt, value) {
|
||||
ingredientNameChange($(evt.target), ingredientSearchEngine);
|
||||
})
|
||||
.on("typeahead:select", function(evt, value) {
|
||||
ingredientItemPicked($(evt.target), value);
|
||||
})
|
||||
.on("typeahead:autocomplete", function(evt, value) {
|
||||
ingredientItemPicked($(evt.target), value);
|
||||
})
|
||||
.on("click", "button.ingredient_convert_btn", function(evt) {
|
||||
|
||||
});
|
||||
|
||||
$('#convert_modal')
|
||||
.on('show.bs.modal', function (event) {
|
||||
var $button = $(event.relatedTarget);
|
||||
var $modal = $(this);
|
||||
|
||||
var $editor = $button.closest(".ingredient-editor");
|
||||
|
||||
$modal.data('ingredient-editor', $editor);
|
||||
|
||||
var $quantity = $editor.find("input.quantity");
|
||||
var $units = $editor.find("input.units");
|
||||
var $ingredientId = $editor.find("input.ingredient_id");
|
||||
|
||||
var $modalQuantity = $modal.find("input.quantity");
|
||||
var $modalUnits = $modal.find("input.units");
|
||||
var $modalIngredientId = $modal.find("input.ingredient_id");
|
||||
|
||||
$modalQuantity.val($quantity.val());
|
||||
$modalUnits.val($units.val());
|
||||
$modalIngredientId.val($ingredientId.val());
|
||||
})
|
||||
.on("ajax:success", "form", function(evt, data, status, xhr) {
|
||||
var $modal = $("#convert_modal");
|
||||
var $editor = $modal.data('ingredient-editor');
|
||||
|
||||
if (data.success) {
|
||||
var $quantity = $editor.find("input.quantity");
|
||||
var $units = $editor.find("input.units");
|
||||
|
||||
var $modalOutUnits = $modal.find("input.output_units");
|
||||
|
||||
$quantity.val(data.output_quantity);
|
||||
if ($modalOutUnits.val().length) {
|
||||
$units.val($modalOutUnits.val());
|
||||
}
|
||||
|
||||
$modal.modal('hide');
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
$("#modal_form_container").replaceWith($(data.form_html));
|
||||
});
|
||||
|
||||
var $bulkIngredientsModal = $("#bulk_ingredients_modal");
|
||||
var $ingredientBulkInput = $("#ingredient_bulk_input");
|
||||
var $ingredientBulkList = $("#ingredient_bulk_parsed_list");
|
||||
autosize($ingredientBulkInput);
|
||||
|
||||
$bulkIngredientsModal
|
||||
.on('show.bs.modal', function (event) {
|
||||
$ingredientBulkInput.val('');
|
||||
$ingredientBulkList.empty();
|
||||
autosize.update($ingredientBulkInput);
|
||||
});
|
||||
|
||||
$ingredientBulkInput.on('keyup', function() {
|
||||
var data = $ingredientBulkInput.val();
|
||||
$ingredientBulkList.empty();
|
||||
|
||||
var parsed = [];
|
||||
var x;
|
||||
|
||||
var lines = data.replace("\r", "").split("\n");
|
||||
|
||||
var regex = /^(?:([\d\/.]+(?:\s+[\d\/]+)?)\s+)?(?:([\w-]+)(?:\s+of)?\s+)?(\w[\w ,\-\(\)\/'"]*)$/i;
|
||||
|
||||
var magicFunc = function(str) {
|
||||
if (str == "-") {
|
||||
return "";
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
for (x = 0; x < lines.length; x++) {
|
||||
var line = lines[x].trim();
|
||||
if (line.length == 0) { continue; }
|
||||
|
||||
var match = line.match(regex);
|
||||
|
||||
if (match) {
|
||||
parsed.push({quantity: magicFunc(match[1]), units: magicFunc(match[2]), name: magicFunc(match[3])});
|
||||
} else {
|
||||
parsed.push(null);
|
||||
}
|
||||
}
|
||||
|
||||
$bulkIngredientsModal.data("bulkData", parsed);
|
||||
|
||||
for (x = 0; x < parsed.length; x++) {
|
||||
var item = parsed[x];
|
||||
if (item != null) {
|
||||
$ingredientBulkList.append(
|
||||
$("<tr />")
|
||||
.append($("<td />").addClass("quantity").text(item.quantity))
|
||||
.append($("<td />").addClass("units").text(item.units))
|
||||
.append($("<td />").addClass("name").text(item.name))
|
||||
);
|
||||
} else {
|
||||
$ingredientBulkList.append(
|
||||
$("<tr />")
|
||||
.append($("<td />").attr("colspan", "3").text("<Cannot Parse>"))
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#bulkIngredientAddSubmit").on("click", function() {
|
||||
var parsed = $bulkIngredientsModal.data("bulkData");
|
||||
var x;
|
||||
|
||||
if (parsed && parsed.length) {
|
||||
for (x = 0; x < parsed.length; x++) {
|
||||
var item = parsed[x];
|
||||
if (item) {
|
||||
addIngredient(item.quantity, item.units, item.name, item.ingredient_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$bulkIngredientsModal.modal('hide')
|
||||
});
|
||||
|
||||
|
||||
// ===========================================
|
||||
// ===========================================
|
||||
|
||||
|
||||
var $bulkStepsModal = $("#bulk_steps_modal");
|
||||
var $stepBulkInput = $("#step_bulk_input");
|
||||
var $stepBulkList = $("#step_bulk_parsed_list");
|
||||
autosize($stepBulkInput);
|
||||
|
||||
$bulkStepsModal
|
||||
.on('show.bs.modal', function (event) {
|
||||
$stepBulkInput.val('');
|
||||
$stepBulkList.empty();
|
||||
autosize.update($stepBulkInput);
|
||||
});
|
||||
|
||||
$stepBulkInput.on('keyup', function() {
|
||||
var data = $stepBulkInput.val();
|
||||
$stepBulkList.empty();
|
||||
|
||||
var parsed = [];
|
||||
var x;
|
||||
|
||||
var lines = data.replace("\r", "").split("\n\n");
|
||||
|
||||
for (x = 0; x < lines.length; x++) {
|
||||
var line = lines[x].trim().replace(/^\d+\./, "").trim();
|
||||
if (line.length == 0) { continue; }
|
||||
|
||||
parsed.push(line);
|
||||
}
|
||||
|
||||
$bulkStepsModal.data("bulkData", parsed);
|
||||
|
||||
for (x = 0; x < parsed.length; x++) {
|
||||
var item = parsed[x];
|
||||
if (item != null) {
|
||||
$stepBulkList.append(
|
||||
$("<tr />")
|
||||
.append($("<td />").addClass("step").text(x + 1))
|
||||
.append($("<td />").addClass("direction").text(item))
|
||||
);
|
||||
} else {
|
||||
$stepBulkList.append(
|
||||
$("<tr />")
|
||||
.append($("<td />").attr("colspan", "2").text("<Cannot Parse>"))
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#bulkStepAddSubmit").on("click", function() {
|
||||
var parsed = $bulkStepsModal.data("bulkData");
|
||||
var x;
|
||||
|
||||
if (parsed && parsed.length) {
|
||||
for (x = 0; x < parsed.length; x++) {
|
||||
var item = parsed[x];
|
||||
if (item) {
|
||||
addStep(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$bulkStepsModal.modal('hide')
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
})(jQuery);
|
||||
|
@ -1,2 +1,4 @@
|
||||
|
||||
$brand-primary: darken(#93C54B, 10%);
|
||||
$text-color: #3E3F3A;
|
||||
|
||||
|
@ -64,4 +64,8 @@ div.recipe-view {
|
||||
.steps div {
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
li.checked {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
@ -8,12 +8,14 @@
|
||||
<p>No Ingredients</p>
|
||||
<% else %>
|
||||
|
||||
<table class="table">
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>USDA NDBN</th>
|
||||
<th>KCal per 100g</th>
|
||||
<th>Density</th>
|
||||
<th colspan="3"></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@ -21,8 +23,14 @@
|
||||
<% @ingredients.each do |ingredient| %>
|
||||
<tr>
|
||||
<td><%= link_to ingredient.name, edit_ingredient_path(ingredient) %></td>
|
||||
<td><%= ingredient.ndbn %></td>
|
||||
<td><%= ingredient.kcal %></td>
|
||||
<td><%= ingredient.density %></td>
|
||||
<td><%= link_to 'Destroy', ingredient, method: :delete, data: { confirm: 'Are you sure?' } %></td>
|
||||
<td>
|
||||
<%= link_to ingredient, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-sm btn-danger' do %>
|
||||
<span class="glyphicon glyphicon-remove"></span>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="recipe-view">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-10">
|
||||
<div class="col-xs-12">
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
<%= @recipe.name %>
|
||||
@ -15,19 +15,6 @@
|
||||
<%= @recipe.description %>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<div class="dropdown">
|
||||
<button id="scaleLabel" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Scale
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="scaleLabel">
|
||||
<% ['1/4', '1/3', '1/2', '2/3', '3/4', '1', '1 1/2', '2', '3', '4'].each do |scale| %>
|
||||
<li><%= link_to scale, scale_recipe_path(@recipe, scale) %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
@ -55,7 +42,27 @@
|
||||
<div class="col-xs-12 col-sm-5 col-md-4">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Ingredients</h3>
|
||||
|
||||
<div class="row">
|
||||
<h3 class="panel-title col-xs-7">Ingredients</h3>
|
||||
<div class="dropdown col-xs-5">
|
||||
<button id="scaleLabel" type="button" class="pull-right btn btn-xs btn-default" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Scale
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="scaleLabel">
|
||||
<% ['1/4', '1/3', '1/2', '2/3', '3/4', '1', '1 1/2', '2', '3', '4'].each do |scale| %>
|
||||
<% if scale == '1' %>
|
||||
<li><%= link_to scale, @recipe %></li>
|
||||
<% else %>
|
||||
<li><%= link_to scale, scale_recipe_path(@recipe, scale) %></li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<ul class="ingredients">
|
||||
|
Loading…
Reference in New Issue
Block a user