Why when a user clicks a link in the list does it cause the browser to flicker? This seems to be very apparent when a user clicks the same 'link' twice. Is there a way for me to remove this from happening?
It also appears to happen if you click a link that scrolls upwards instead of down. To test this click the list item 'Test' and then click 'Why'
https://jsfiddle.net/JokerMartini/9vne9423/
Here is the main JS bits which are doing all the work...
JS
function scroll_to_element(element) {
$('html, body').animate({scrollTop: $(element).offset().top}, 500);
}
$(window).ready(function() {
$(".nav-title").click(function() {
var target = $(this);
// get data-filter text
var title = target.data('title').toLowerCase();
// collect section titles
sections = $( ".section-title" );
// loop through and scroll to valid section
for (i = 0; i < sections.length; i++) {
var section = $(sections[i]);
var section_title = section.data('title').toLowerCase();
if (section_title === title) {
scroll_to_element(section)
// console.log(target);
}
}
});
});
You should prevent the default behavior of the anchor tag before invoking your custom functionality:
$(".nav-title").click(function(e) {
e.preventDefault();
});
Updated Fiddle
put href="javascript:void(0);" instead of href="#" attribute in your "What is", "Why" and "Test1" links
jsfiddle
Related
I have some Bootstrap vertical tabs that I'm struggling with what I felt like would be a simple operation.
Goal:
On the click of Tab, I want to smooth-scroll to the corresponding pane.
What's Actually Happening:
On click of the tab, the browser animates to the tab, not the tab pane. I've tried passing in the paneId instead of the ID, but that doesn't work at all. Any idea where I'm going wrong?
Codepen:
Here's a Codepen: Codepen!
jQuery:
$("#tabs .nav-link").click(function (e) { //on click of nav tav, perform this:
var id = $(e.target).prop("id"); //Grab ID of .nav-link clicked
var paneId = id.replace("tab", "pane"); //Replace "tab" with "pane" and assign new var
function navigateToElement(id) {
$("html, body").animate(
{
scrollTop: $("#" + id).offset().top
},
300
);
}
navigateToElement(id); //Tried with "paneId" instead of "id" to scroll to the pane, but doesn't work
});
Any idea where I'm going wrong?
This line:
var paneId = id.replace("tab", "pane"); //Replace "tab" with "pane" and assign new var
Is creating a variable like: v-pills-profile-pane and there isn't a div on the page with that id. I did see a div with id="v-pills-profile". Change that last line to this and it should work:
var paneId = id.replace("-tab", "");
I just realized that it doesn't matter what pane I scroll to, as bootstrap will display the panes under #panes. As long as I can scroll to that, I'm good. This code worked:
$("#tabs .nav-link").click(function (e) {
var target = $("#panes");
$([document.documentElement, document.body]).animate(
{
scrollTop: $(target).offset().top - 20, // added a bit of offset
},
350
);
});
I hope you have a good day :)
I am working on a plugin currently. I would like to loop through all the articles: on click => open a popp-up, when the pop-up closes => show this content ... My code only works for the first article. Sorry if that seems trivial to you, if you have links or tutorials to advise me, I am interested :)
Thank you !
function socialLocker() {
let sl = document.querySelector(".ws-sl-container");
let slc = document.querySelector(".ws-sl-content");
document.querySelectorAll(".ws-sl-box-for-social-medias a").forEach(function(ele) {
ele.onclick = function(e) {
var web_window = window.open(this.href, 'Share Link', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=600,width=600,top=' + (screen.height/2 - 300) + ',left=' + (screen.width/2 - 300));
var check_window_close = setInterval(function() {
if (web_window.closed) {
clearInterval(check_window_close);
sl.style.display = "none";
slc.style.display = "block";
}
}, 1000);
e.preventDefault();
};
});
};
It seems to be a problem with selecting the elements in the document.
You can use next selector: https://api.jquery.com/next/ instead of selecting all and looping with foreach. With next, you will get the closest element.
Suppose all the posts in your list have a button with the class trigger and when clicked it shows a popup with the class of popup.
<script>
jQuery(document).ready(function(){
jQuery(".popup").hide(); /* hide all popups */
jQuery(".trigger").click(function(){ /* when button is clicked */
jQuery(this).next(".popup").slideToggle(); /* toggle the closest popup */
});
});
</script>
This way the click / action (you want to have it when closed) on (this) element will affect nearest element.
I'm creating an additional tab on a menu dynamically (let's call this new tab, Watch), and all was going pretty well including the submenu that showed up once the new tab was hovered over. I looked at articles on event bubbling and took a look at other examples, but couldn't find a solution to my issue.
Whenever I hover over Watch, the submenu appears, but when I try to hover from Watch to its submenu, the submenu disappears. I need the submenu to persist when a user hovers over Watch or the submenu, and the submenu should only disappear once the user hovers out of either. Just to note, I cannot use CSS for my solution. I've attached my current code below with comments:
//PREPEND AS FIRST CHILD
var prependChild = function(parent, newFirstChild) {
parent.insertBefore(newFirstChild, parent.firstChild)
}
//DECLARING VARS
var navMenu = document.getElementsByClassName('navGlobal-list')[0];
categoryExplorer = document.getElementsByClassName('categoryExplorer')[0];
//CREATING NEW TAB
var exploreTab = document.createElement('li');
exploreTab.className = 'navGlobal-category';
//CREATING NEW SEARCH FORM
var searchHtml = ['<div class="searchProgram searchProgram--categoryExplorer">',
'<div class="searchProgram-container">',
'<input type="search" class="form-control form-control--light form-control--searchProgram" placeholder="Search programs" value="">',
'</div>',
'</div>'].join('');
//CREATING NEW WATCH CATEGORY EXPLORER CONTENT
var watchCategoryExplorerContent = document.createElement('div');
watchCategoryExplorerContent.className = 'categoryExplorer-content target-watch-content';
watchCategoryExplorerContent.innerHTML = searchHtml;
prependChild(categoryExplorer, watchCategoryExplorerContent)
var watchLink = document.createElement('a');
watchLink.setAttribute('href','/watch');
watchLink.innerHTML = 'watch'.toUpperCase();
exploreTab.appendChild(watchLink);
navMenu.appendChild(exploreTab); //ADDED 'WATCH' TO THE NAVIGATION
//CHANGE CLASSES ON HOVER
exploreTab.addEventListener("mouseover", function() {
exploreTab.className = 'navGlobal-category navGlobal-category--open';
categoryExplorer.className = 'categoryExplorer categoryExplorer--open';
watchCategoryExplorerContent.className = 'categoryExplorer-content categoryExplorer-content--open target-watch-content';
}, false);
exploreTab.addEventListener("mouseleave", function() {
exploreTab.className = 'navGlobal-category';
categoryExplorer.className = 'categoryExplorer';
watchCategoryExplorerContent.className = 'categoryExplorer-content target-watch-content';
}, false);
A potential (layout-dependent) way to keep the menu open would be to make it a child of the tab - that way, provided there is no space between the tab and the hover menu, you can hover from one to the other without creating a mouseleave event on the tab.
Another solution that is not layout-dependent would be to add some delay between the initial mouseleave event and the submenu closing. I've done something like this using jQuery before, but the same thing should be possible without it.
$('.navGlobal-category').mouseleave(function(){
setTimeout(
function(){
if(!isHovered($('.navGlobal-category')[0])){
exploreTab.className = 'navGlobal-category';
categoryExplorer.className = 'categoryExplorer';
watchCategoryExplorerContent.className = 'categoryExplorer-content target-watch-content';
}
}, 200);
});
function isHovered(e){
return ((e.parentNode.querySelector(":hover") ||
e.querySelector(":hover")) === e);
}
Credit to zb' for the isHovered solution: https://stackoverflow.com/a/14800287/5403341
For the non-layout solution #B1SeeMore suggests you don't actually need a delay.
Here is a working demo: https://jsfiddle.net/jw22ddzk/
<div id="one" class="menuitem"></div>
<div id="two" class="menuitem" style="display: none;"></div>
var elems = document.getElementsByClassName("menuitem");
for (var i = 0; i < elems.length; i += 1) {
elems[i].addEventListener("mouseleave", function () {
console.log("leave", this.id);
document.getElementById("two").style.display = "none";
});
elems[i].addEventListener("mouseenter", function () {
console.log("enter", this.id);
document.getElementById("two").style.display = "";
});
}
The trick is that mouseenter fires for two even if mouseleave hides the element. Just remember to show the element again. A likey explanation is that the mouseenter and mouseleave events spawn in pairs. So mouseenter happens regardless of the effects of mouseleave.
Note that this only works if the elements are beside eachother with pixel accuracy.
Another note: I notice that you're using mouseover and mouseleave. I wouldn't recommend doing that. There are two event pairs for detecting hovers: mouseenter/leave and mouseover/out. They are different events. They differ specifically in that mouseover/out will trigger also for child elments. My recommendation is that you don't interchange the pairs or you might get unexpected behaviour.
I can't figure out why the second gallery doesn't scroll like the first one
Here's a link:
Here's the jQuery that makes it work:
$(function(){
var state = 0;
var maxState = 7;
var winWidth = $('#sub').width();
$('#sub').resize(function(){
winWidth = $('#sub').width();
$('.gallerybox,.container_element').width(winWidth-110);
$('.container_element').scrollLeft((winWidth-110)*state);
}).trigger('resize');
$('#lefty').click(function(){
if (state==0) {
state = maxState;
} else {
state--;
}
$('.container_element').animate({scrollLeft:((winWidth-100)*state)+'px'}, 800);
});
$('#righty').click(function(){
if (state==maxState) {
state = 0;
} else {
state++;
}
$('.container_element').animate({scrollLeft:((winWidth-100)*state)+'px'}, 800);
});
});
Both navigation bars have the same id. Hence, when you search for id in jQuery it will stop searching once it founds the very first result. So it won't get your second navigation tab.
Change the id, or use a class selector.
By the way, you should post the html here, not link the productive site
I have these icons above each section on my page (the largish circular icons, please see example: http://pftest.fhero.net) with colored hover states... what I would really love to do is have them change to the active hover states as the user scrolls to each section (preferably with a simple fade transition) - much like the effect of highlighting the active links/section in the navigation.
There are many tutorials, plugins and questions on this site and so forth for highlighting active sections in a navigation however, but doesn't seem to be much that I can find relating to applying the effect to another div or image on the page...
I'm definitely not any kind of jQuery expert but I'm wondering if one of the myriad of scripts/plugins available which are typically used for highlighting active states in navigation could simply be adapted to this scenario somehow to achieve the same effect? Perhaps even the one I am currently using on my page?
Here is the script I'm using for highlighting the active section in the navigation on my page:
/* Scroll Navigation highlight */
$("#work-section1").parent().addClass('active');
var main = main = $('#mainmenu ul');
$('.scroll').click(function(event) {
event.preventDefault();
var full_url = this.href,
parts = full_url.split('#'),
trgt = parts[1],
target_offset = $('#'+trgt).offset(),
target_top = target_offset.top;
$('html, body').animate({scrollTop:target_top}, 500);
/* Remove active class on any li when an anchor is clicked */
main.children().removeClass();
/* Add active class to clicked anchor's parent li */
$(this).parent().addClass('active');
});
$(window).scroll(function(event) {
if($("#work-section").offset().top < $(window).scrollTop() + $(window).outerHeight()){
$("#work-section1").parent().addClass('active');
$("#about-section1").parent().removeClass('active');
$("#footer-section").parent().removeClass('active');
$("#services-section1").parent().removeClass('active');
$("#process-section1").parent().removeClass('active');
}
if($("#about-section").offset().top < $(window).scrollTop() + $(window).outerHeight()) {
$("#about-section1").parent().addClass('active');
$("#work-section1").parent().removeClass('active');
$("#footer-section1").parent().removeClass('active');
$("#services-section1").parent().removeClass('active');
$("#process-section1").parent().removeClass('active');
}
if($("#services-section").offset().top < $(window).scrollTop() + $(window).outerHeight()){
$("#services-section1").parent().addClass('active');
$("#about-section1").parent().removeClass('active');
$("#work-section1").parent().removeClass('active');
$("#footer-section1").parent().removeClass('active');
$("#process-section1").parent().removeClass('active');
}
if($("#process-section").offset().top < $(window).scrollTop() + $(window).outerHeight()){
$("#process-section1").parent().addClass('active');
$("#about-section1").parent().removeClass('active');
$("#work-section1").parent().removeClass('active');
$("#footer-section1").parent().removeClass('active');
$("#services-section1").parent().removeClass('active');
}
if($("#footer-section").offset().top < $(window).scrollTop() + $(window).outerHeight()){
$("#footer-section1").parent().addClass('active');
$("#about-section1").parent().removeClass('active');
$("#work-section1").parent().removeClass('active');
$("#services-section1").parent().removeClass('active');
$("#process-section1").parent().removeClass('active');
}
});
and the HTML:
<nav id="mainmenu" name="mainmenu">
<ul>
<li><a class="scroll" id="work-section1" href="#work-section">Works</a></li>
<li><a class="scroll" id="about-section1" href="#about-section">About</a></li>
<li><a class="scroll" id="services-section1" href="#services-section">Services</a></li>
<li><a class="scroll" id="process-section1" href="#process-section">Process</a></li>
<li><a class="scroll" id="footer-section1" href="#footer-section">Contact</a></li>
</ul>
</nav>
<section id="about-section" data-anchor-offset="90">
<section id="work-section" data-anchor-offset="90">
...ect...
Could this somehow be adapted to accomplish the effect I am looking for? Or any other/better methods, or plugins I should be looking at?
I should add that the icons use the sprites method which could make the CSS side of things a little trickier, although I would be willing to change them to non-sprite images if necessary...
You could use a small little function for this, that checks if a element is on screen. I set up a little JSFiddle for you: http://jsfiddle.net/LHrkB/1/
Code:
function isElementVisible(elementToBeChecked)
{
var TopView = $(window).scrollTop();
var BotView = TopView + $(window).height();
var TopElement = $(elementToBeChecked).offset().top;
var BotElement = TopElement + $(elementToBeChecked).height();
return ((BotElement <= BotView) && (TopElement >= TopView));
}
$(window).scroll(function () {
isOnView = isElementVisible(".inview");
if(isOnView){
//What to do when element is visible
$(".inview").css({"background":"#ccc"});
}else{ // If not visible
}
});
Ok, so i have changed the JSFiddle a bit, now it uses a fadeIn on a invisible element when it comes into view: http://jsfiddle.net/LHrkB/2/
Ok, i changed the JSFiddle once again. When you scroll in the results pane, and you play around with it a bit you can see the element change class as it comes on screen and also when it goes away again. I commented the JS so you can see what it does and where it does it. http://jsfiddle.net/LHrkB/4/
Thanks to the help of Veritas87 (who is super awesome), managed to get it all working with the following code:
function isElementVisible(elementToBeChecked)
{
var TopView = $(window).scrollTop();
var BotView = TopView + $(window).height();
var TopElement = $(elementToBeChecked).offset().top;
var BotElement = TopElement + $(elementToBeChecked).height();
return ((BotElement <= BotView) && (TopElement >= TopView));
}
$(window).scroll(function () {
isOnView = isElementVisible(".about-icon");
if(isOnView){
//What to do when element is visible
$('.about-icon').addClass('about-icon-active');
}else{ // If not visible
$('.about-icon').removeClass('about-icon-active');
}
isOnView = isElementVisible(".works-icon");
if(isOnView){
//What to do when element is visible
$('.works-icon').addClass('works-icon-active');
}else{ // If not visible
$('.works-icon').removeClass('works-icon-active');
}
isOnView = isElementVisible(".services-icon");
if(isOnView){
//What to do when element is visible
$('.services-icon').addClass('services-icon-active');
}else{ // If not visible
$('.services-icon').removeClass('services-icon-active');
}
isOnView = isElementVisible(".process-icon");
if(isOnView){
//What to do when element is visible
$('.process-icon').addClass('process-icon-active');
}else{ // If not visible
$('.process-icon').removeClass('process-icon-active');
}
});
with the "...icon-active" classes of course containing the style for the icon hover states.