Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialChris Shaffer
12,030 PointsMy Solution: Plugin Challenge "Sticky.js"
I just wanted to provide my solution to this challenge. It's a bit different than what is shown in the video, but probably because the video focuses on a literal solution without any JQuery shortcuts.
Here I'm selecting a single element, which would more ideally be done using an ID instead of a sub-element; but as this is a simple HTML project, it's okay.
$(".grid-full h5").sticky({
topSpacing:64
});
$(".grid-full h5").on('sticky-start', function(){
$(this).html('Want us to work on your project?' + '<a href="mailto" class="email-link"> Email Us</a>');
$(this).on('sticky-end', function(){
$(this).html('Want us to work on your project?');
});
});
I then offset the variation in header
height in the CSS:
@media (max-width: 852px) {
.grid-full h5 {
margin-top: 56px;
}
}
@media (max-width: 700px) {
.grid-full h5 {
margin-top: 50px;
}
}
I used 852px because Chrome now applies a break point automatically at this level. There's no need to adjust on the @media
at 1000px, and 700px just needs a small tweak.
Hope that helps anyone looking for similar solutions!
4 Answers
Iain Simmons
Treehouse Moderator 32,305 PointsHi Chris Shaffer, I just wanted to mention a couple of things about your solution.
First, because you have the sticky-end
event handler nested within the sticky-start
one, you'll be binding a new event handler every time the user scrolls back to the top.
Second, while using html
in this case works fine, it's much slower than append
and remove
, which can also have increased performance by using a variable for the new a
element.
You can also chain the on
methods.
As for the CSS, I found just removing or commenting out the opacity: .95;
on the existing .is-sticky h5
rule seemed to do the trick (though your solution might avoid that little jump
of the content below when it sticks).
Here was my JS code (I also just stuck in within some script tags on the work.html page, so it doesn't run on every other page).
var emailLink = $('<a href="mailto:help@teamtreehouse.com">Email us</a>');
$(document).ready(function(){
$("h5").sticky({topSpacing:64})
.on('sticky-start', function() {
$(this).append(" ").append(emailLink);
})
.on('sticky-end', function() {
emailLink.remove();
});
});
Chris Shaffer
12,030 PointsIain, thanks for the feedback.
True, I hadn't considered the addition of a new event handler each time. Do you if chaining eliminates this?
My understandIng is that JQuery chaining is similar to nesting due to the backend JQuery functions effectively executing as though they are nested, but that might be wrong.
Also, my understanding of the '''.html''' method is that it is effectively the same as
$().append();
. If I understand from the JQuery API, ```
$().append();
$().remove();
can be used for exactly what they would appear to be: appending and removing to existing HTML, where in contrast
html
$().html();
is effectively setting the value (almost like
$(this). append().val();
``` in concept.
I'll have to take a closer look at the API docs.
Iain Simmons
Treehouse Moderator 32,305 PointsYes, chaining eliminates the additional event handlers.
Chaining is different from nesting. Chaining is just a shortcut instead of having duplicate selectors for multiple method calls. The below code is the same as my chained code.
$("h5").sticky({topSpacing:64});
$("h5").on('sticky-start', function() {
$(this).append(" ").append(emailLink);
});
$("h5").on('sticky-end', function() {
emailLink.remove();
});
Nesting, on the other hand, means that one event handler/function will only be called when the outer function is called, but also every time it is called.
You don't want to bind the event handler every time the sticky-end
is fired, you just want to bind it once and run the function every time the sticky-end
event is fired.
append
and remove
will add and remove DOM nodes, whereas html
will change a property of the DOM node (presumably the innerHTML). I already mentioned why this is a good thing.
Javier Gandia
Full Stack JavaScript Techdegree Student 9,153 Points$(".grid-full h5").on("sticky-start", function(){
const gridH5 = document.querySelector(".grid-full h5").innerHTML;
const email = ` <a href="mailto:javierggandia@yahoo.com">Email us</a>`
$(this).append(email).on("sticky-end",function (){
$(this).empty(email).append(gridH5);
});
});
my solution.. works like a charm..
Chris Shaffer
12,030 PointsI marked Ian's answer as best due to the explanation of best practices.
Javier, while your answer uses chaining, it also unnecessarily uses the document.querySelector method in a way that is not recommended due to unpredictable results.
That method should generally only be used when the first element with the class you are targeting is going to change dynamically. jQuery would be able to easily target the element ID which is exact specificity - the preferred method when said element will remain static.