I'm working a single-page website for my friend's photo studio: http://dev.manifold.ws/yorckstudio/
The site is divided in six sections, each the size of the viewport. When you click on one of the menu item, it takes you to the corresponding section. What I can't figure out is how to get a menu item to be underline when viewing the corresponding section. So if I'm viewing the "Photos" section, the item "Photos" in my fixed menu would be underlined.
My guess is that there must be a relatively simple way to achieve that with a bit of javascript / jQuery magic. But my js skills being quite poor, I'm not sure where to start.
Does anyone have a idea of how this could be achieved?
Cheers,
Thom
Using jQuery, add this is your JS:
$('#menu a').click(function(){
$(this).css('text-decoration','underline');
$(this).parent().siblings().find('a').css('text-decoration','none');
})
This will add an underline to the clicked anchor tags and remove the attribute on all the other ones.
jsFiddle: http://jsfiddle.net/z97RX/
Try this:
$('#menu ul li a').click(function(){
var that = $(this);
that.addClass('underline');
that.parent().siblings().find('a').removeClass('underline');
});
And add to css
.underline{
text-decoration: underline;
}
If you could, please take a look here http://jsfiddle.net/xv8tf/3/
It could be cleaned up a bit, but here is the jist of it.
All you require to do on your end is update you menu and your scrollto elements and just add a rel tag with matching values
Example:
<div id="menu">
<ul>
<li><a rel="photos" href="javascript:void(0)">Photos</a></li>
</ul>
</div>
<div rel="photos" id="photos"></div>
//create a list of all elements to be tested against
var scrollMatches = [
$('#photos'),
$('#studio'),
$('#rates'),
$('#features'),
$('#plan'),
$('#contact')
];
$(window)
.on('scroll', function(){
//save scrolltop to var to prevent multiple callings
var scroll = $(this).scrollTop();
//iterate through each of the elements to be testing against
$.each(scrollMatches, function(k, v){
var offset = v.offset()
// if the element is in the viewport
if(offset.top <= scroll && (offset.top + v.outerHeight()) > scroll){
// get associated element
var element = $('#menu li > a[rel='+v.attr('rel')+']');
// do whatever you want to the current tested element
element.css('text-decoration','underline');
// dp whatever you want to the associated menu item
element.parent().siblings().find('a').css('text-decoration','none');
return false;
}
});
});
Related
I have a sidebar with a ul list, like so:
<div id="sidebar">
<ul>
</ul>
</div>
There is no actual html content in the sidebar because the ul list are being populated through a javascript function. So my javascript function fills in the ul list once the page has finished loading.
The problem is that I want to make this sidebar sticky, but the moment I make it sticky, the content inside the ul list dissapears (as if javascript cant recognize my ul list anymore).
What I tried:
I tried making the sidebar sticky using pure css like "position: sticky"
I tried using the "Sticksy" script from: https://sticksy.js.org/ The sticksy script works great, but the result is the same: my ul list are no longer being filled in by my javascript function.
As mentioned, it's as if javascript can't find the ul list to add the content to, while the sidebar is sticky. Any advice on how to get around this?
EDIT: (here is the function that ads code to my ul list)
var summaryWidgetList = document.querySelector("#sidebar ul");
function mySummary() {
var selectionList = document.querySelectorAll("#site-main .product-title");
selectionList.forEach(selectionItem => {
var selectionItemTag = document.createElement("li");
selectionItemTag.innerHTML = selectionItem.textContent;
summaryWidgetList.appendChild(selectionItemTag);
})
}
window.addEventListener('load', mySummary);
Well, try to append data to your ul element.
Create ID for ul element:
<ul id="list">
</ul>
Now append the <li> elements in your desired way to "list" element.
F.ex. using vanilla JavaScript:
document.getElementById("list").innerHTML += "<li> filled </li>"
I created a very simple example:
https://playcode.io/695917/
OK, so I am sorry if this question is repeated BUT I really could not figure answer.
O have menu with classes, and I want that when I click on some menu items .menuitem > a
that link have more paddingBottom.
So I managed to use .click function and animate function but that add padding to entire class ( all menu items ).
What I need is adding padding only to THAT CLICKED menu.
Code that make padding to all menu items ( entire class )
$(".menuitem" ).click(function() {
$('.mainNav > ul > li > a').animate({paddingBottom:"+=17px"});
});
when I click on some menu items .menuitem > a that link have more paddingBottom
Within the click handler, the particular .menuitem element that was clicked can be referred to by this. Thus, using $(this) you can use jQuery's DOM traversal method(s) to move from that element to the related one you want to animate.
If the anchor is a child of the .menuitem element that you are binding the click handler to then the simplest way to get a reference to that anchor is with the .find() method:
$( ".menuitem" ).click(function() {
$(this).find("a").animate({paddingBottom:"+=17px"});
});
you can use this key word to select your 'a' tag which you click on it now 'only'
$('.menuitem').click(function(){
$(this).find('a').animate({'padding':'+=17px'});
});
or more specific
$('.menuitem li').click(function(){
$(this).find('a').animate({'padding':'+=17px'});
});
Here's the HTML I'm focusing on:
<nav>
<ul id='nav'>
<li></icon>Home<span> +</span></li>
<li><icon><img src="images/skills-icon.png"></icon>Skillsets</li>
<li><icon><img src="images/gallery-icon.png"></icon>Gallery</li>
<li><icon><img src="images/about-icon.png"></icon>About</li>
<li></icon>Contact</li>
</ul>
</nav>
I want to select the text within the span—preferably only the "+" part of the text within the span (without the space). The way I'm trying to do that right now is with this code:
$(document).ready(function(){
var ul = $('nav > ul'),
li = ul.children('li'),
top = li.find('a').hasClass("top"),
navSpan = $(top).children('span');
$(navSpan).contents().replaceWith(' -');
});
but it isn't selecting the element correctly. With the way I have my javascript set up (there's a lot more of it than this) I need to keep these variables. However, it appears that some of these variables aren't set up correctly, or that my $(navSpan).contents().replaceWith() command isn't set up correctly. Do you guys have any ideas on how to fix it? Thanks!
First of all, lets fix your selectors and your double-wrapping:
$(function(){
var ul = $('#nav'),
li = ul.children('li'),
top = li.find('a.top'), // you can remove the 'a' qualifier if there is never another item with the top class
navSpan = top.children('span');
Second of all ... you can just replace the contents with this:
navSpan.text(' -');
});
Final code:
$(function(){
var ul = $('#nav'),
li = ul.children('li'),
top = li.find('a.top'),
navSpan = top.children('span');
navSpan.text(' -');
});
I cringe a little bit at the volume of unnecessary variables in this example, but you said you need all of them so I won't try to further optimize.
EDIT: Couldn't resist optimizing a little. Even if you need to capture all of those variables, you will have a faster querying with an id than you will using nav > li. If you have multiple menus that this applies to then disregard, but if not then this would be a little faster.
Here is a jsFiddle of the working code.
hasClass returns a boolean value. If you want to filter an element, you can use the filter method: li.find('a').filter(".top")
contents returns the childNodes of an element, you can't call jQuery methods on the returned value.
$('nav > ul').find('a.top span').text(' -');
I am trying to get a 3rd level menu to automatically expand when its first level parent is expanded. So in the example I have, when you hover over the first item I want the Item 1 submenu to show (like normal) and then also the first submenu under that. Item 2 should also be showing. http://jsfiddle.net/n2Sxc/1/
I have tried to use this code, which is in the jsfiddle.
$("#main-nav li").mouseover(function () {
$("#main-nav li ul li.first ul").show();
});
I have also looked at the api documentation, but it isn't really clear to me how to use expand or focus. I'm not sure if that's even what I want to use.
Focus: http://api.jqueryui.com/menu/#event-focus
Expand: http://api.jqueryui.com/menu/#method-expand
I have also tried this when initiating the menu
$('#main-nav').menu({
focus: function( focus, ui ) {
$("#main-nav li").hover(function (){
$("#main-nav li ul li.first ul").show();
});
}
});
Yes, focus and expand is what you need. You don't need .show().
I am not sure whether your mouseover will not conflict with the normal menu events handling.
For the beginning, to get at least something simple working, a code like below could automatically expand the submenus after menu creation (to simplify the selectors maybe you could add ids to your menu items, I have doubts whether your selectors select what intended):
$("#main-nav").menu()
.menu("focus",null,$("#main-nav > li.first"))
.menu("expand")
.menu("focus",null,$("#main-nav > li.first > ul > li.first"))
.menu("expand");
In the current jquery-ui-1.10.3 + jquery-2.0.3 this code actually fails with some null element access... It is a bug in jquery. I can't find the bug ticket now but I saw that it was already resolved and will be ok in the next release.
I'm currently trying to use Quicksand, a jquery plugin that allows you to animate elements on the page by hiding and showing certain elements based on tags. I have that working just fine. My problem is that as the elements are easing, they enlarge while they're moving. Once they settle in their places, they shrink to the proper size, but it looks awfully strange and I'd like to work out why this is happening in the first place.
Here is the main.js file that has my preferences for quicksand:
$(document).ready(function() {
// get the action filter option item on page load
var $filterType = $('#filterOptions li.active a').attr('class');
// get and assign the ourHolder element to the
// $holder varible for use later
var $holder = $('ul.ourHolder');
// clone all items within the pre-assigned $holder element
var $data = $holder.clone();
// attempt to call Quicksand when a filter option
// item is clicked
$('#filterOptions li a').click(function(e) {
// reset the active class on all the buttons
$('#filterOptions li').removeClass('active');
// assign the class of the clicked filter option
// element to our $filterType variable
var $filterType = $(this).attr('class');
$(this).parent().addClass('active');
if ($filterType == 'all') {
// assign all li items to the $filteredData var when
// the 'All' filter option is clicked
var $filteredData = $data.find('li');
}
else {
// find all li elements that have our required $filterType
// values for the data-type element
var $filteredData = $data.find('li[data-type~=' + $filterType + ']');
}
// call quicksand and assign transition parameters
$holder.quicksand($filteredData, {
duration: 800,
easing: 'easeInOutQuad'
});
return false;
});
});
The Quicksand file itself has remained the same, with the except that I changed all 'height's within the document to 'width', as I don't have heights specified for any of the divs.
Thank you for your help! Please let me know if you need to see the HTML or CSS to solve the problem.
This is happening because of the easing function you've used: easeInOutQuad.
It gives the animation an invese bounce aspect.
See here for reference: http://gsgd.co.uk/sandbox/jquery/easing/
Edit:
You have found your problem since start. I've debuged your page and found that the percentage measures are the problem.
From the site: http://razorjack.net/quicksand/docs-and-demos.html
CSS recommendations
1.When styling your items and their container, please use CSS class. Using ID may lead to strange results. Quicksand clones the container to simulate destination frame of the animation. Since it's impossible for two elements of the same ID to exist, styling your items/container via container ID should be avoided.
2.Quicksand needs to know the margin of body, container and collection items. If these elements have their margins, please use px (pixels), not ems. The plugin doesn't understand ems for now.
I think percentages are included in this same case.