Skip to content
This repository was archived by the owner on Apr 29, 2022. It is now read-only.

Commit 44d8c19

Browse files
author
Koen Werdler
committed
Improvements to cooking recipes form
1 parent b6d2cd7 commit 44d8c19

12 files changed

+338
-17
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
TODO:
2+
* Add possibility to add ingredients on new/edit recipe form
3+
* Add possibility to add units on new/edit recipe form
4+
* Add management of ingredients
5+
* Add management of units
6+
* Add extra description to necessity. For example '1/2 small onion, diced'
7+
* Add preparation time and cooking time to recipe
8+
* Add number of servings to recipe.

app/assets/javascripts/cooking_recipes.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,11 @@ initialize_sorting = function() {
3737
// $( "#sortable-items" ).disableSelection();
3838
};
3939

40-
$(document).ready(initialize_sorting);
41-
$(document).on('page:load', initialize_sorting);
40+
initialize = function() {
41+
initialize_sorting();
42+
43+
$("textarea[name$='[description]']").autosize();
44+
}
45+
46+
$(document).ready(initialize);
47+
$(document).on('page:load', initialize);
+273
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
/*!
2+
Autosize 1.18.17
3+
license: MIT
4+
http://www.jacklmoore.com/autosize
5+
*/
6+
(function ($) {
7+
var
8+
defaults = {
9+
className: 'autosizejs',
10+
id: 'autosizejs',
11+
append: '\n',
12+
callback: false,
13+
resizeDelay: 10,
14+
placeholder: true
15+
},
16+
17+
// border:0 is unnecessary, but avoids a bug in Firefox on OSX
18+
copy = '<textarea tabindex="-1" style="position:absolute; top:-999px; left:0; right:auto; bottom:auto; border:0; padding: 0; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden; transition:none; -webkit-transition:none; -moz-transition:none;"/>',
19+
20+
// line-height is conditionally included because IE7/IE8/old Opera do not return the correct value.
21+
typographyStyles = [
22+
'fontFamily',
23+
'fontSize',
24+
'fontWeight',
25+
'fontStyle',
26+
'letterSpacing',
27+
'textTransform',
28+
'wordSpacing',
29+
'textIndent',
30+
'whiteSpace'
31+
],
32+
33+
// to keep track which textarea is being mirrored when adjust() is called.
34+
mirrored,
35+
36+
// the mirror element, which is used to calculate what size the mirrored element should be.
37+
mirror = $(copy).data('autosize', true)[0];
38+
39+
// test that line-height can be accurately copied.
40+
mirror.style.lineHeight = '99px';
41+
if ($(mirror).css('lineHeight') === '99px') {
42+
typographyStyles.push('lineHeight');
43+
}
44+
mirror.style.lineHeight = '';
45+
46+
$.fn.autosize = function (options) {
47+
if (!this.length) {
48+
return this;
49+
}
50+
51+
options = $.extend({}, defaults, options || {});
52+
53+
if (mirror.parentNode !== document.body) {
54+
$(document.body).append(mirror);
55+
}
56+
57+
return this.each(function () {
58+
var
59+
ta = this,
60+
$ta = $(ta),
61+
maxHeight,
62+
minHeight,
63+
boxOffset = 0,
64+
callback = $.isFunction(options.callback),
65+
originalStyles = {
66+
height: ta.style.height,
67+
overflow: ta.style.overflow,
68+
overflowY: ta.style.overflowY,
69+
wordWrap: ta.style.wordWrap,
70+
resize: ta.style.resize
71+
},
72+
timeout,
73+
width = $ta.width(),
74+
taResize = $ta.css('resize');
75+
76+
if ($ta.data('autosize')) {
77+
// exit if autosize has already been applied, or if the textarea is the mirror element.
78+
return;
79+
}
80+
$ta.data('autosize', true);
81+
82+
if ($ta.css('box-sizing') === 'border-box' || $ta.css('-moz-box-sizing') === 'border-box' || $ta.css('-webkit-box-sizing') === 'border-box'){
83+
boxOffset = $ta.outerHeight() - $ta.height();
84+
}
85+
86+
// IE8 and lower return 'auto', which parses to NaN, if no min-height is set.
87+
minHeight = Math.max(parseFloat($ta.css('minHeight')) - boxOffset || 0, $ta.height());
88+
89+
$ta.css({
90+
overflow: 'hidden',
91+
overflowY: 'hidden',
92+
wordWrap: 'break-word' // horizontal overflow is hidden, so break-word is necessary for handling words longer than the textarea width
93+
});
94+
95+
if (taResize === 'vertical') {
96+
$ta.css('resize','none');
97+
} else if (taResize === 'both') {
98+
$ta.css('resize', 'horizontal');
99+
}
100+
101+
// getComputedStyle is preferred here because it preserves sub-pixel values, while jQuery's .width() rounds to an integer.
102+
function setWidth() {
103+
var width;
104+
var style = window.getComputedStyle ? window.getComputedStyle(ta, null) : null;
105+
106+
if (style) {
107+
width = parseFloat(style.width);
108+
if (style.boxSizing === 'border-box' || style.webkitBoxSizing === 'border-box' || style.mozBoxSizing === 'border-box') {
109+
$.each(['paddingLeft', 'paddingRight', 'borderLeftWidth', 'borderRightWidth'], function(i,val){
110+
width -= parseFloat(style[val]);
111+
});
112+
}
113+
} else {
114+
width = $ta.width();
115+
}
116+
117+
mirror.style.width = Math.max(width,0) + 'px';
118+
}
119+
120+
function initMirror() {
121+
var styles = {};
122+
123+
mirrored = ta;
124+
mirror.className = options.className;
125+
mirror.id = options.id;
126+
maxHeight = parseFloat($ta.css('maxHeight'));
127+
128+
// mirror is a duplicate textarea located off-screen that
129+
// is automatically updated to contain the same text as the
130+
// original textarea. mirror always has a height of 0.
131+
// This gives a cross-browser supported way getting the actual
132+
// height of the text, through the scrollTop property.
133+
$.each(typographyStyles, function(i,val){
134+
styles[val] = $ta.css(val);
135+
});
136+
137+
$(mirror).css(styles).attr('wrap', $ta.attr('wrap'));
138+
139+
setWidth();
140+
141+
// Chrome-specific fix:
142+
// When the textarea y-overflow is hidden, Chrome doesn't reflow the text to account for the space
143+
// made available by removing the scrollbar. This workaround triggers the reflow for Chrome.
144+
if (window.chrome) {
145+
var width = ta.style.width;
146+
ta.style.width = '0px';
147+
var ignore = ta.offsetWidth;
148+
ta.style.width = width;
149+
}
150+
}
151+
152+
// Using mainly bare JS in this function because it is going
153+
// to fire very often while typing, and needs to very efficient.
154+
function adjust() {
155+
var height, originalHeight;
156+
157+
if (mirrored !== ta) {
158+
initMirror();
159+
} else {
160+
setWidth();
161+
}
162+
163+
if (!ta.value && options.placeholder) {
164+
// If the textarea is empty, copy the placeholder text into
165+
// the mirror control and use that for sizing so that we
166+
// don't end up with placeholder getting trimmed.
167+
mirror.value = ($ta.attr("placeholder") || '');
168+
} else {
169+
mirror.value = ta.value;
170+
}
171+
172+
mirror.value += options.append || '';
173+
mirror.style.overflowY = ta.style.overflowY;
174+
originalHeight = parseFloat(ta.style.height) || 0;
175+
176+
// Setting scrollTop to zero is needed in IE8 and lower for the next step to be accurately applied
177+
mirror.scrollTop = 0;
178+
179+
mirror.scrollTop = 9e4;
180+
181+
// Using scrollTop rather than scrollHeight because scrollHeight is non-standard and includes padding.
182+
height = mirror.scrollTop;
183+
184+
if (maxHeight && height > maxHeight) {
185+
ta.style.overflowY = 'scroll';
186+
height = maxHeight;
187+
} else {
188+
ta.style.overflowY = 'hidden';
189+
if (height < minHeight) {
190+
height = minHeight;
191+
}
192+
}
193+
194+
height += boxOffset;
195+
196+
if (Math.abs(originalHeight - height) > 1/100) {
197+
ta.style.height = height + 'px';
198+
199+
// Trigger a repaint for IE8 for when ta is nested 2 or more levels inside an inline-block
200+
mirror.className = mirror.className;
201+
202+
if (callback) {
203+
options.callback.call(ta,ta);
204+
}
205+
$ta.trigger('autosize.resized');
206+
}
207+
}
208+
209+
function resize () {
210+
clearTimeout(timeout);
211+
timeout = setTimeout(function(){
212+
var newWidth = $ta.width();
213+
214+
if (newWidth !== width) {
215+
width = newWidth;
216+
adjust();
217+
}
218+
}, parseInt(options.resizeDelay,10));
219+
}
220+
221+
if ('onpropertychange' in ta) {
222+
if ('oninput' in ta) {
223+
// Detects IE9. IE9 does not fire onpropertychange or oninput for deletions,
224+
// so binding to onkeyup to catch most of those occasions. There is no way that I
225+
// know of to detect something like 'cut' in IE9.
226+
$ta.on('input.autosize keyup.autosize', adjust);
227+
} else {
228+
// IE7 / IE8
229+
$ta.on('propertychange.autosize', function(){
230+
if(event.propertyName === 'value'){
231+
adjust();
232+
}
233+
});
234+
}
235+
} else {
236+
// Modern Browsers
237+
$ta.on('input.autosize', adjust);
238+
}
239+
240+
// Set options.resizeDelay to false if using fixed-width textarea elements.
241+
// Uses a timeout and width check to reduce the amount of times adjust needs to be called after window resize.
242+
243+
if (options.resizeDelay !== false) {
244+
$(window).on('resize.autosize', resize);
245+
}
246+
247+
// Event for manual triggering if needed.
248+
// Should only be needed when the value of the textarea is changed through JavaScript rather than user input.
249+
$ta.on('autosize.resize', adjust);
250+
251+
// Event for manual triggering that also forces the styles to update as well.
252+
// Should only be needed if one of typography styles of the textarea change, and the textarea is already the target of the adjust method.
253+
$ta.on('autosize.resizeIncludeStyle', function() {
254+
mirrored = null;
255+
adjust();
256+
});
257+
258+
$ta.on('autosize.destroy', function(){
259+
mirrored = null;
260+
clearTimeout(timeout);
261+
$(window).off('resize', resize);
262+
$ta
263+
.off('autosize')
264+
.off('.autosize')
265+
.css(originalStyles)
266+
.removeData('autosize');
267+
});
268+
269+
// Call adjust in case the textarea already contains text.
270+
adjust();
271+
});
272+
};
273+
}(jQuery || $)); // jQuery or jQuery-like library, such as Zepto

app/assets/stylesheets/cooking_recipes_form.css.scss

+21-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
border-radius: 8px;
44
margin-bottom: 5px;
55
padding:8px 0px;
6+
7+
textarea {
8+
-webkit-transition: height 0.2s;
9+
-moz-transition: height 0.2s;
10+
transition: height 0.2s;
11+
}
612
}
713

814
.sortable-placeholder {
@@ -28,13 +34,24 @@
2834

2935
.sortable-index-display {
3036
display: inline-block;
31-
height: 50px;
37+
height: 60px;
3238
vertical-align: top;
33-
color: #CCC;
34-
width: 65%;
39+
color: #EFEFEF;
40+
width: 55%;
3541

36-
font-size: 50px;
42+
font-size: 98px;
3743
font-weight: bold;
3844
text-align: center;
3945
line-height: 50px;
4046
}
47+
48+
#image_columns div:nth-child(6n) {
49+
&:after {
50+
clear:both;
51+
display: table;
52+
}
53+
&:before {
54+
content: " ";
55+
display: table;
56+
}
57+
}

app/controllers/cooking_recipes_controller.rb

+14
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ def new
1010

1111
def create
1212
@cooking_recipe = CookingRecipe.new(cooking_recipe_params)
13+
14+
if params[:images] && params[:images][0].present?
15+
params[:images].each do |file|
16+
@cooking_recipe.images.build(file: file)
17+
end
18+
end
19+
1320
if @cooking_recipe.save
1421
flash[:notice] = 'Recipe saved'
1522
redirect_to cooking_recipes_path
@@ -43,6 +50,13 @@ def show
4350
@cooking_recipe = CookingRecipe.find(params[:id])
4451
end
4552

53+
def destroy
54+
@cooking_recipe = CookingRecipe.find(params[:id])
55+
@cooking_recipe.destroy
56+
flash[:notice] = 'Recipe removed'
57+
redirect_to cooking_recipes_path
58+
end
59+
4660
def add_necessity_fields
4761
end
4862

app/models/cooking_recipe.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
class CookingRecipe < ActiveRecord::Base
2-
has_many :necessities
3-
has_many :directions
2+
has_many :necessities, dependent: :destroy
3+
has_many :directions, dependent: :destroy
44

5-
has_many :images, as: :imageable
5+
has_many :images, as: :imageable, dependent: :destroy
66

77
accepts_nested_attributes_for :necessities, allow_destroy: true
88
accepts_nested_attributes_for :directions, allow_destroy: true

0 commit comments

Comments
 (0)