calculator
This commit is contained in:
parent
9cc9fb2c2f
commit
ffb2c92f74
@ -18,4 +18,5 @@
|
||||
//= require typeahead
|
||||
//= require autosize
|
||||
//= require chosen.jquery
|
||||
//= require underscore
|
||||
//= require_tree .
|
||||
|
73
app/assets/javascripts/calculator.js
Normal file
73
app/assets/javascripts/calculator.js
Normal file
@ -0,0 +1,73 @@
|
||||
(function($) {
|
||||
|
||||
function State() {
|
||||
this.input = null;
|
||||
this.outputUnit = null;
|
||||
this.changed = false;
|
||||
}
|
||||
|
||||
State.prototype.setInput = function(value) {
|
||||
if (value != this.input) {
|
||||
this.changed = true;
|
||||
this.input = value;
|
||||
}
|
||||
};
|
||||
|
||||
State.prototype.setOutputUnit = function(value) {
|
||||
if (value != this.outputUnit) {
|
||||
this.changed = true;
|
||||
this.outputUnit = value;
|
||||
}
|
||||
};
|
||||
|
||||
State.prototype.is_changed = function() {
|
||||
return this.changed;
|
||||
};
|
||||
|
||||
State.prototype.reset = function() {
|
||||
this.changed = false;
|
||||
};
|
||||
|
||||
$(document).on("ready page:load", function() {
|
||||
|
||||
var state = new State();
|
||||
var $input = $("#input");
|
||||
var $output = $("#output");
|
||||
var $outputUnit = $("#output_unit");
|
||||
|
||||
var performUpdate = _.debounce(function() {
|
||||
$.getJSON(
|
||||
"/calculator/calculate",
|
||||
{input: $input.val(), output_unit: $outputUnit.val()},
|
||||
function(data) {
|
||||
if (data.errors.input) {
|
||||
$input.closest(".form-group").addClass("has-error");
|
||||
} else {
|
||||
$input.closest(".form-group").removeClass("has-error");
|
||||
}
|
||||
|
||||
if (data.errors.output_unit) {
|
||||
$outputUnit.closest(".form-group").addClass("has-error");
|
||||
} else {
|
||||
$outputUnit.closest(".form-group").removeClass("has-error");
|
||||
}
|
||||
|
||||
$output.val(data.output);
|
||||
}
|
||||
);
|
||||
|
||||
}, 500);
|
||||
|
||||
$input.add($outputUnit).on('change blur keyup', function(evt) {
|
||||
state.setInput($input.val());
|
||||
state.setOutputUnit($outputUnit.val());
|
||||
|
||||
if (state.is_changed()) {
|
||||
performUpdate();
|
||||
state.reset();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})(jQuery);
|
45
app/controllers/calculator_controller.rb
Normal file
45
app/controllers/calculator_controller.rb
Normal file
@ -0,0 +1,45 @@
|
||||
class CalculatorController < ApplicationController
|
||||
|
||||
def index
|
||||
|
||||
end
|
||||
|
||||
def calculate
|
||||
input = params[:input]
|
||||
output_unit = params[:output_unit]
|
||||
parsed_input = nil
|
||||
original_number = nil
|
||||
|
||||
data = {errors: {}, output: ''}
|
||||
|
||||
if input.present?
|
||||
|
||||
begin
|
||||
parsed_input = UnitConversion.parse(input)
|
||||
original_number = parsed_input.value
|
||||
rescue UnitConversion::UnparseableUnitError => e
|
||||
data[:errors][:input] = [e.message]
|
||||
end
|
||||
|
||||
if parsed_input.present? && output_unit.present?
|
||||
begin
|
||||
parsed_input = parsed_input.convert_to output_unit
|
||||
rescue Unitwise::ExpressionError => e
|
||||
data[:errors][:output_unit] = [e.message]
|
||||
end
|
||||
end
|
||||
|
||||
if parsed_input
|
||||
puts parsed_input.value
|
||||
puts parsed_input.unit
|
||||
data[:output] = UnitConversion.auto_unit(UnitConversion.quantity_format(parsed_input.value, original_number), parsed_input.unit.to_s)
|
||||
end
|
||||
|
||||
else
|
||||
data[:errors][:input] = ['Invalid input']
|
||||
end
|
||||
|
||||
render json: data
|
||||
end
|
||||
|
||||
end
|
@ -2,7 +2,7 @@ class IngredientsController < ApplicationController
|
||||
|
||||
before_action :set_ingredient, only: [:edit, :update, :destroy]
|
||||
|
||||
before_filter :ensure_valid_user, only: [:new, :edit, :create, :update, :destroy]
|
||||
before_filter :ensure_valid_user, except: [:index]
|
||||
|
||||
# GET /ingredients
|
||||
# GET /ingredients.json
|
||||
|
@ -2,7 +2,7 @@ class RecipesController < ApplicationController
|
||||
|
||||
before_action :set_recipe, only: [:show, :edit, :update, :destroy, :scale]
|
||||
|
||||
before_filter :ensure_valid_user, only: [:new, :edit, :create, :update, :destroy]
|
||||
before_filter :ensure_valid_user, except: [:show, :scale, :index]
|
||||
|
||||
# GET /recipes
|
||||
def index
|
||||
@ -24,7 +24,6 @@ class RecipesController < ApplicationController
|
||||
# GET /recipes/new
|
||||
def new
|
||||
@recipe = Recipe.new
|
||||
@recipe.recipe_ingredients << RecipeIngredient.new
|
||||
end
|
||||
|
||||
# GET /recipes/1/edit
|
||||
|
@ -8,6 +8,7 @@ module ApplicationHelper
|
||||
[
|
||||
nav_item('Recipes', recipes_path, 'recipes'),
|
||||
nav_item('Ingredients', ingredients_path, 'ingredients'),
|
||||
nav_item('Calculator', calculator_path, 'calculator'),
|
||||
nav_item('About', about_path, 'home')
|
||||
]
|
||||
end
|
||||
|
@ -118,6 +118,7 @@ module UnitConversion
|
||||
end
|
||||
|
||||
def normalize_unit_names(unit_description)
|
||||
return unit_description.to_sym if UNIT_ALIASES.include?(unit_description.to_sym)
|
||||
unit_description.downcase.gsub(/[a-z]+/) do |match|
|
||||
UNIT_ALIAS_MAP[match] || match
|
||||
end
|
||||
|
26
app/views/calculator/index.html.erb
Normal file
26
app/views/calculator/index.html.erb
Normal file
@ -0,0 +1,26 @@
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Calculator</h1>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="form-group col-xs-12 col-sm-8">
|
||||
<%= label_tag :input, "Input", class: 'control-label' %>
|
||||
<%= text_field_tag :input, nil, class: 'form-control', autofocus: true %>
|
||||
</div>
|
||||
<div class="form-group col-xs-12 col-sm-4">
|
||||
<%= label_tag :output_unit, "Output Unit", class: 'control-label' %>
|
||||
<%= text_field_tag :output_unit, nil, class: 'form-control' %>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-xs-12">
|
||||
<%= label_tag :output, "Output", class: 'control-label' %>
|
||||
<%= text_field_tag :output, nil, class: 'form-control', readonly: true %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
@ -4,7 +4,7 @@
|
||||
|
||||
<div class="form-group">
|
||||
<%= f.label :username, class: 'control-label' %>
|
||||
<%= f.text_field :username, class: 'form-control' %>
|
||||
<%= f.text_field :username, autofocus: true, class: 'form-control' %>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<%= f.label :full_name, 'Name', class: 'control-label' %>
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
<div class="form-group">
|
||||
<%= label_tag :username, "Username", class: 'control-label' %>
|
||||
<%= text_field_tag :username, nil, class: 'form-control' %>
|
||||
<%= text_field_tag :username, nil, autofocus: true, class: 'form-control' %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -28,6 +28,11 @@ Rails.application.routes.draw do
|
||||
|
||||
get '/about' => 'home#about', as: :about
|
||||
|
||||
scope '/calculator', controller: :calculator, as: :calculator do
|
||||
get '/' => :index
|
||||
get '/calculate' => :calculate
|
||||
end
|
||||
|
||||
root 'recipes#index'
|
||||
|
||||
|
||||
|
@ -21,6 +21,7 @@ RSpec.describe UnitConversion do
|
||||
expect(UnitConversion.auto_unit('1/16', 'cup')).to eq ['1', 'tablespoon']
|
||||
expect(UnitConversion.auto_unit('1/48', 'cup')).to eq ['1', 'teaspoon']
|
||||
expect(UnitConversion.auto_unit('768', 'tsp')).to eq ['1', 'gallon']
|
||||
expect(UnitConversion.auto_unit('6', '[tsp_us]')).to eq ['2', 'tablespoon']
|
||||
end
|
||||
|
||||
it 'converts standard mass units correctly' do
|
||||
|
1548
vendor/assets/javascripts/underscore.js
vendored
Normal file
1548
vendor/assets/javascripts/underscore.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user