-: Hey there! So let's now continue building our recipe view.
So in case you don't remember,
where we left off is that we now want
to create a small function which basically converts
these decimal numbers here into fractions.
So here, for example, we would have four and a half,
here we would have one quarter,
here we would have one and three quarters,
and so on and so forth. Okay.
Now in order to do that,
we will actually use a small external third-party package,
because coming up with all this code
would be a bit too much for this lecture.
And so it's a great opportunity to show you how
to include, once more, external packages
through the npm package manager.
So the one that we're gonna use is called fraction.js
and it's just a very small, very simple library
which will allow us to basically put in a number
and then get a numerator and a denominator
out of that number, okay?
So for example, if you were input 0.75,
it would give us a numerator of three
and a denominator of four, so three quarters.
So all we need to do is to go ahead
and use npm install fractional
in our terminal,
and not the process that it's running,
but of course this one here.
And we also want to save it in our package-adjacent pile.
And here we go. So, let's take a look at that.
Indeed! Here you go. So fractional is now available to us.
And so we can go ahead and import that.
So we will import
and it is a named export,
and I'm going to show it to you in a second--
from, and now we just need the fractional.
So again, for an external package installed through npm,
we don't need to include the path.
And actually this one is called fraction,
and not fractional, okay?
So this package doesn't have a really good documentation,
but I know that it's exporting a named export
called fraction because that's what we see here.
So this here is another way of importing modules
with an older syntax, okay?
So this is like the node.js syntax,
and not the ES6 syntax that we've been using.
But it requires here this package and then the .Fraction.
And so this here is the one that we're looking for
and the one that we imported over here,
so that's a named export.
You can also see that,
in the index.js file-- this is not really important,
but just in case that you need to know this kind of stuff.
So you see here module.export.fraction
and so you see that it has a named export called fraction.
And so that's the one that we're importing
here now at the top of our file.
Okay, so let's create a function here called
form-at-the-count...
where you put in a count, so basically a number,
and then we're gonna return a formatted string.
And we're then going to go ahead
and use that here in the render recipe.
Or actually, it's in the create ingredient.
Okay, so it's right here.
So we pass that in into format in the count.
And this will then return a better formatted number here
instead of the raw number that we have
in our data in our object.
So let's start out by asking if we actually have a count.
Because it is possible that, from our data processing,
the count is actually undefined.
So imagine before that there might be some unsolved cases
here in the parse ingredients,
and so it might sometimes return undefined for the count.
So usually that's not the case, but it might happen,
and so in that case all this code
that we're gonna put here is not going to run.
And instead we can simply return something like this,
so instead a question mark, okay?
So instead of saying "undefined" in either interface,
it will have this question mark
which is gonna look much nicer.
So let's pretend that our example here is 2.5 as the count,
so just that we have an example here
in order to know how to build up this code.
Now this is then later going to translate into two
and one-half, right, so just as a reference.
Now the fourth thing that I want to do is
to separate the integer part from the decimal part.
Cause imagine if it were 0.5, then it would look different,
and let's actually take that as an example as well.
So if it was 0.5, then we would just have a half,
and that's of course a different situation here.
So let's start by doing that.
And now we are going to use something called destructuring,
and I hope you remember that from ES2015 or ES6 section.
So basically we can define two variables
here at the same time. And you're gonna see why in a second.
So we have our count. We will convert it to a string,
so use tostring.
So now we can split it,
and of course split it by deduct,
and so this will now be an array
of a two and a five both as strings in this example here.
In 2.5 we will now have the integer
as two and the decimal as five.
Now the only problem with that is
that they are now both strings
and you want them to be as numbers.
So we need a new array with them as numbers,
and so we can use map, right?
And we're gonna do in here is to simply parse
the element with a base of ten.
And so now we're gonna have two and five both
relay as numbers in these two variables, right?
Now, in case there is no decimal,
which is perfectly acceptable,
then we must simply return the count.
Imagine that we have just two.
So if we have two, then we will have no decimal at all,
and so we can simply return the original count,
which was two, and call it a day
because then no work is really done here at this point.
So that's the first case actually, but now let's say
"if the integer
is zero".
And so that would be this case here.
So integer is zero, and five is the decimal, so 0.5.
And so now comes the case where we actually want to convert
0.5 to a string looking like this, so to one half.
So how do we do that?
Well, we're gonna use the fraction library now.
So we create a new variable, and I'm simply gonna call
it fr, which stands for fractional,
and then we say "new fraction...
based on count".
Okay. So based on count it will now create a fraction,
and from there we can read the numerator and the denominator
And so, what we're gonna return here is a string,
so a template string
with fr
numerator,
then a slash-- and actually without the space,
and then fr.denominator.
And so in case we have 0.5, well,
this will automatically calculate that the numerator is one
and the denominator is two, okay?
And so then we're gonna return one half, just like this,
and with that we're done with the formatting
in case that the integer is zero.
Now if it's not so, for example 2.5,
well then it's a bit different.
So we still need to create a new fraction,
but really we don't want to create
a new fraction of all of this.
We just want to create the new fraction of the 0.5 still,
cause otherwise we would simply end up with five halves,
so we could have this intermediate
step here like five halves, so that's the same.
But we don't wanna display it like this, which is still 2.5,
but it looks better like this, so two and a half.
That's a bit more logical, right? It makes more sense.
And so what we really want is to
create a fraction just of the 0.5 part,
and what that means is that we simply have to do count minus
the integer.
Right? And then from there it's actually pretty similar.
So this part here,
now all that's missing is of course--
and I hope you can guess it-- the integer part.
So we do this fraction here only with 2.5 minus two, right?
So count is 2.5 and integer is two.
So 2.5 minus two will be point five,
which will be then one half.
And then here in this return statement
in this template string we put it back together, basically.
So we put our two and then our one half, which is this.
Okay, so once more this is really not for you
to memorize how this specific case works,
I just want you to be able to think logically, basically,
about how we can achieve the goals we need to achieve, okay?
And in this case there are some particularities,
like having to do it this way here, for example.
But that should now work, so let's test it out.
And we're still ordering the same recipe
and indeed, here we go!
So we have four and a half, one and three quarters,
one quarter, and one and three quarters.
So that's perfect; it works just fine.
And now one last thing that I want to implement here
is the functionality that basically the recipe
that we select here from our search list
will then get selected with this gray background here.
So right now it's this pizza here, so this one is gray,
and if I select this one here, well,
then this one here stays gray. Okay.
So that shouldn't be all too hard,
so let's go back to our code and quickly implement that.
And we actually want this to happen when a recipe loads,
but the time and implementation itself
happens in a search view, okay?
So let's actually add a method
or function here in the search view, and I'm gonna call it,
let's say, the "highlight selected".
And so for that I need an ID of course,
and so let's see how we can do that.
So what I'm gonna do is document a query selector of course,
because it's an element that's not
yet there when we load the page.
And so I can do it in my base.js,
so in my elements object that we've been using so far.
So query selector, and so now we can use the power
of the CSS selectors because actually
that's what we can input here.
So this is like a CSS selector, as you know already,
and so we can select all links based on attributes
and the attribute that we're looking for is the href.
And we want to say that it has the ID.
Simple as this. So we have a link always with the
hash symbol and then the ID, right?
So let's take a look at the search list just to make sure
that we're on the same page here.
So the links they are, as you can see,
down there and also up here.
It's always the hash and then the ID, right?
And so we want to select the element that,
as an href attribute, has exactly this ID here,
so this hash, okay?
So you want to select it and then, on the class list,
add the class of
result link active.
And again, I could put this here into the--
Where is it? It's not this one.
So I could put it here into the element strings,
but I'm not going to keep this one here,
because then if something changes
I will have to actually change it here in element strings
and also in the code that I put in here.
So, like in here. I would have to go ahead
and add these element strings,
also here inside of all this markup that I input here.
And that's way too much work,
and so I'm not going to go that way.
I'm just gonna leave it as it is.
Okay, so I'm just going to hard-code these class names here,
just as I do it also down here.
Okay so here we also have all of these hard-coded basically.
So, results links-- and that's actually the one
where this new class will be attached--
so result links and, if it's active,
then we have result__link--active.
And actually, yeah, it is results and not just result.
And so now you see it's the same result link active
and then result link if it is not active.
Okay, so now it's selected, and now let's go ahead
into our controller
and say highlight
the selected search item.
And of course we have to do it again
in the recipe controller because this only happens
as soon as we load a recipe, alright?
So, searchview.highlightSelected,
and then the ID.
Okay let's take a look at it and it will not be perfect yet,
and you will see why in a second.
So if I hit it now here--
Well, then it's actually not really working at all.
So let's check out the console here.
So what do we have here?
It says here that it's not a valid selector,
and so let's see why that is.
Yeah, we can close this one, I guess,
for now and the recipe as well.
And so the problem here is that we are
lacking some quotes here, okay?
So in CSS in the selector here,
you have to put it into quotes.
So let's check it out again,
and now it says it cannot read class list of null.
And so that's actually another error,
which is that in this case there was not really a search,
and so how can we highlight a search
result that's not really there?
So let's add an if-clause before that, so if state
dot search-- so if this exists,
then it means that there was a search,
and only then one of the search items can be selected.
Okay, so let's wait for it.
And it still says it can't read class list of null,
and I'm not sure why that is, so let's check it out again.
I guess it must be somewhere here.
So indeed, this quote is not in the right place.
It should be here.
So this is here what goes inside the quotes,
so just the ID with the hash.
And of course, this quote cannot be outside of this bracket.
Try it one more time.
Ah, here it is.
No, it's still not working. What's going on here?
Well, it doesn't give me an error anymore.
Let's try another one here.
And it's still not working, as you can see here.
And so, let's try it one more time.
Now, what's wrong is this.
So when we add a class to the class list,
we cannot put the dot selector
because the dot is just a selector.
And so here we really just need to pass
in the class name and not the selector.
Okay, and so that should now finally fix it.
So let's try it out again here.
We're adding pizza, and let's just click the first one here.
And now it stays active! Okay, great.
Now the only problem is that when I click this one here
then the other is still active.
And when I click this and this and this,
and so all of them now they stay active.
And so a very simple solution to that is to--
Whoa, what's happening here now?
I guess I clicked on too many of them at the same time.
So what I have to do here is,
before adding the class to one of them,
I have to remove it from all of them first,
So let's just select them all first
and put them into a variable,
and I'm gonna call it results array.
And so I'm making Array.from,
which I already explained in the ES6 section.
So document.query
Selectorall,
and the ones that I'm looking for is this results link.
And again I'm not using it from the element strings.
But instead I'm simply hard-coding it right here,
so I'm not boring you here in this video
and make them longer and longer than they really have to be.
So this is an array now, and now finally results dot array.
And then for each of them,
let's simply remove
the class.
So elements dot class list dot remove,
and then let's just get it from here.
And what was that? Okay.
Alright, great!
Just the final test now.
Now let's select this one and let's hope it works.
And, indeed, it removes it from there.
So it really works.
So, I guess we're done with this part.
Now, there's just one thing that there's left to implement,
so they can look at it here again.
And that is of course the functionality where we can
decrease and increase the servings.
So you see, whenever I hit this button here
or decrease button, then all of these numbers here--
so the count numbers of the ingredients,
they all get automatically updated.
And so that's what we're still missing,
and so we're gonna take care of that
right in the next lecture. So, see you there.