Is there an easy way to highlight a top with id (apply css-class with specific color f.e.) after user scrolls to it? I have a scrollspy on page, but it seems that plugin will not help me, so I can't make to ends meet.
P.S. I didn't find alike info in Google or StackOverflow, so please, don't get me wrong.
There is a rough example of page
https://jsfiddle.net/masyurik/kdnzdeb2/#&togetherjs=DeaMiBADpp
HTML
<div id="secA" class="section">
Hello it's secA
<div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
<div id="secB" class="section">
Hello it's secB
<div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
<div id="secC" class="section">
Hello it's secC
<div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
CSS
.section {
background-color: red;
}
.active {
background-color: yellow;
}
You need to use scrollevent and change the class accordingly... kindly check https://jsfiddle.net/77v3329y/1/
jQuery
$(document).ready(function() {
var a = +$('#secA').height();
var b = $('#secB').height();
var c = $('#secC').height();
console.log(a);
console.log(b);
console.log(c);
$(window).on('scroll', function() {
$('#secA, #secB, #secC').removeClass('active');
var st = $(document).scrollTop();
if (st < a) {
$('#secA').addClass('active');
}
if (st > a) {
$('#secB').addClass('active');
}
if (st > a + b) {
$('#secC').addClass('active');
}
})
});
You can use jquery-waypoints to know which element has reached at top of the viewport. The plugin will give you the callback which will help you to change the css of the active element.
Here is the solutions to detect the scroll to top event.
Fire event when div is visible to visitor with jQuery?
Simply use jQuery to change the css of the element when scroll to top: $("#secA").css("background-color", "yellow");
Related
On one of my websites I want to remove a specific HTML element if the screen is smaller than 767px (on mobile devices).
The following piece of HTML is used 9 times on the page:
<div class="price-list__item-desc"> </div>
So all 9 pieces of HTML have to be removed only on mobile devices.
I already included the following jQuery file on the website:
jQuery(function ($) {
if (window.matchMedia('(max-width: 767px)').matches) {
$('<div class="price-list__item-desc"> </div>').hide();
}
else {
$('<div class="price-list__item-desc"> </div>').show();
}
});
However, the code is not working and the pieces of HTML still show up on mobile devices. I know there might be a very easy fix for this particular objective. But after searching the internet for two days I have come across so many different options that actually made me more confused.
Would very much appreciate any help, thanks in advance!
In the first method, when the page width changes, the div.price-list__item-desc element is hidden or shown using jQuery by controlling the page width.
In the method you developed, the anonymous function is not run to hide the item when the page changes; you need to use event handler method. In the structure I developed, the onresize event is affected when the page width changes. This way I can catch this event when the page width changes.
$( document ).ready(function() {
window.onresize = function() {
console.log(`Width: ${$( window ).width()}`);
var divs = document.querySelectorAll("div.price-list__item-desc");
if (window.matchMedia('(max-width: 767px)').matches)
{
$('div.price-list__item-desc').removeClass("active");
for (var i = 0; i < divs.length; i++)
{
if(divs[i].innerHTML === ' ')
divs[i].style.display = "none";
else
divs[i].style.display = "block";
}
}
else
{
$('div.price-list__item-desc').addClass("active");
}
}
window.onresize();
});
div.price-list__item-desc {
background-color: red;
display: none;
}
.active{
display: block !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="price-list__item-desc"> </div>
<div class="price-list__item-desc">1</div>
<div class="price-list__item-desc"> </div>
<div class="price-list__item-desc">2</div>
<div class="price-list__item-desc"> </div>
there's nothing calling your function. Use media queries instead.
UPDATE: I added some js to solve your problem. If you are trying to hide (so the div still takes up space but doesn't show anything) then your question doesn't really make sense. If you want to remove the div then set display to none. The js is used to grab the divs that you want
let divs = document.getElementsByClassName('price-list__item-desc')
for(let i = 0; i < divs.length; i++){
if (divs[i].innerHTML == " ")divs[i].classList.add('hide')
}
#media (max-width: 767px) {
.hide{
display:none;}
}
<div class="price-list__item-desc"> </div>
<div class="price-list__item-desc"> </div>
<div class="price-list__item-desc"> </div>
<div class="price-list__item-desc"> </div>
<div class="price-list__item-desc"> </div>
<div class="price-list__item-desc">6</div>
<div class="price-list__item-desc">7</div>
<div class="price-list__item-desc">8</div>
<div class="price-list__item-desc">9</div>
I am trying to find out how to make a class disappear when scrolling up in a browser. I had been able to make a class to appear when a certain height in a browser is met by using this code.
jQuery(".tetapElement").css("opacity", 1);
jQuery(window).scroll(function() {
var windowHeight = jQuery(window).height();
if (windowHeight < 470) {
jQuery(".tetapElement").css("opacity",1);
} else if (windowHeight > 1820) {
jQuery(".tetapElement").css("opacity",1);
}
else {
jQuery(".tetapElement").css("opacity",0);
}
});
.tetapElement {
position:fixed;
top: -30%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!--make another checkout button -->
<div class="tetapElement">
<div class="order_title">Order details:</div>
<div class="order_bar_details">
<div class="pack_name"><?php echo $post->post_title ;?></div>
<div class="pack_name_value">Package name:</div>
<div class="pack_details"></div>
<div class="addon_title">Add-On Menu</div>
<div class="addon_details"></div>
</div>
<div class="order_price">Total price (<?php echo $currency; ?>): <span class="total_price">0</span></div>
<div class="chekout_link">
<textarea id="order_details" style="display:none;" name="order_details" ></textarea>
<?php wp_nonce_field('process_checkout_action','process_checkout_field'); ?>
<input type="submit" class="btn btn-success checkout_btn mk-flat-button shop-black-btn" value="Checkout">
</div>
</div>
you can see it in action in here. so that when you click on that link and reduce your browser height then another class would pop up. But I need to finds way how to make that class to disappear again when a user scroll up so as not to disturb another class that were put there.
so in essence, I put 2 class. one class will disappear when scrolling down and then replace by another class and I want this another class to disappear also when a user scroll up and replace by original class. any idea how to that in jquery?
A very similar question is asked here.
var lastScrollTop = 0;
$(window).scroll(function(event){
var st = $(this).scrollTop();
if (st < lastScrollTop){
// upscroll code
$(".tetapElement").removeClass("classToRemove");
}
lastScrollTop = st;
});
media query max-height seems to be a better solution if you want to alter css properties in my opinion
Is there any method or JavaScript library that can see if an element is really fully visible? As an example, suppose you need some UI button shown between certain elements and not take up more space on the page, as on this example:
https://jsfiddle.net/akyh7e5f/
html:
<div style="width:50%; display:inline-block">
<div class="a">
<div>
Some content here.
</div>
<div class="inserter">
insertme
</div>
</div>
<div class="b">
<div>
some other content
</div>
</div>
</div>
<div style="width:49%; display:inline-block">
<div class="a" style="z-index:1">
<div>
Some content here.
</div>
<div class="inserter">
insertme
</div>
</div>
<div class="b" style="z-index:2">
<div>
some other content
</div>
</div>
</div>
css:
.a {
height:80%;
background: blue;
position:relative;
}
.b {
padding:30px;
background:green;
position:relative;
}
.inserter {
position:absolute; z-index:9999;
left:50%; margin-left:-20px;
background: red;
}
In one case the element is inside and shows, in the other case it is under because some other element has more zindex than a container of the insertme element. I could make it body > element direct child, but then EVERY change to the height of the element would required a change to the position.
You could move the red element up one dom element until it is after the element and visible, then do some calculations for top/left,
or, perhaps more performant, change it from absolute to relative and make it take up space, in the second case it will not show (which is not as great from a design perspective).
In either of these two cases, I need to know whether the element (red element in this fiddle) is actually visible and clickable with no element above it. Is there any library that can find this?
Please do not reply with a specific suggestion for the jsfiddle - this is a minimal test case, assume many different styles may theme the page in any way, not to mention user-added styles. Also please do not mention Selenium as this has to be a browser-only dynamic app.
Can use elementFromPoint() to test if the element you want is the top element at it's offset coordinates.
This is not a full test for your issue but should help give you part of it
$('.inserter').each(function(){
var offset= $(this).offset();
var topEl = document.elementFromPoint(offset.left, offset.top);
console.log(topEl == this)
})
Note I only checked the top left corner, you would probably want to see if more of it is displayed than just that corner.
DEMO
For puppeteer I needed this and used #charlietfl answer to do it but with more checks
await page.waitForFunction(
(browserSelector) => {
const browserElement = document.querySelector(browserSelector);
if (!browserElement) {
console.log(`Cannot find element "${browserSelector}"`); // eslint-disable-line no-console
return false;
}
const boundingBox = browserElement.getBoundingClientRect();
if (boundingBox.width === 0) {
console.log(`Element "${browserSelector}" has no width`); // eslint-disable-line no-console
return false;
}
if (boundingBox.height === 0) {
console.log(`Element "${browserSelector}" has no height`); // eslint-disable-line no-console
return false;
}
const clickTarget = document.elementFromPoint(
boundingBox.left + boundingBox.width / 2, // Horizontal center
boundingBox.top + boundingBox.height / 2, // Vertical center
);
if (!browserElement.contains(clickTarget)) {
console.log(`Element "${browserSelector}" is obstructed`); // eslint-disable-line no-console
return false;
}
return true;
},
{}, // No options for waitForFunction
selector,
);
Well, i am stucked and can't find the answer myself. Hopefully someone can give me a hint.
I try to fullfill the following requirements:
There should be a Newsblock within a HTML Page with a fixed width and
height.
In this Newsblock only the title of the news are visible.
Those news are "collapsed" by default and should "expand" if the Mouse is over it.
Due the fact that the 'Newsblock' is limited by its height, there should be a Scrollbar visible. But only if the currently expanded news makes it necessary, so the user can Scroll down.
Newstitle and Newstext should never leave the Newsblock.
so far so good, i was able to fullfill all those demands except the one with the Scrollbar. If i try to reach the Scrollbar out of the currently expanded news it collapses again and the Scrollbar disappears. I understand that my .hover is configured that it always SlideUp if i leave the newsentry and the Scrollbar isn't a part of the newsentry div. But i have no idea what to change to still have an overall Scrollbar for the Newsblock, but won't disappear if i try to 'reach' it.
P.s.: A Scrollbar only per Newsentry looks weird. Thats why i want 'bind' the scrollbar to the parent container :S
HTML
<div id="newsblock">
<div> // some auto generated div's i have to life with, so the news entries are not 'direct' children of the newsblock.
<div class="newsentry">
<div class="newstitle">...</div>
<div class="newstext">...</div>
</div>
... another 9 'newsentry' divs.
</div>
</div>
JS
$(".newsentry").hover(
function() {
$(this).children(".newstext").stop(true,true).slideDown();
},
function() {
$(this).children(".newstext").stop(true,true).slideUp();
}
);
CSS
.newsblock {
height: 200px;
overflow-y: auto;
}
Instead of closing a .newsentry when the cursor goes out of it, a solution can be to close it only when it enters another .newsentry or when it leaves #newsblock.
The scrollbar being part of #newsblock, the entry isn't closed anymore when you go on it.
EDIT: Following our discussion about the scroll issue, I added a step callback to the closing animation to make sure that the top of the .newsentry getting opened remains visible when the other entries are getting closed.
Here is a working example:
var $newsblock = $("#newsblock");
function closeAllNews(slideUpArgs){
return $(".newstext").stop(true).slideUp(slideUpArgs);
}
function openNews(news, slideDownArgs){
$(news).find(".newstext").stop(true).slideDown(slideDownArgs);
}
function ensureNewsTopVisible(news){
// Check if the top of the newsentry is visible...
var top = $(news).position().top;
if(top < 0){
// ...and if not, scroll newsblock accordingly.
$newsblock.scrollTop($newsblock.scrollTop() + top);
}
}
$(".newsentry").each(function(){
var $this = $(this);
// When the mouse enter a news entry...
$this.on("mouseenter", function(){
// ...close all opened entries (normally there is at most one)...
closeAllNews({
// (while making sure that the top of this entry remains visible
// at each step)
step: ensureNewsTopVisible.bind(null, $this)
});
// ...open this newsentry.
openNews($this);
});
});
// When the mouse get out of the newsblock, close all news.
$newsblock.on("mouseleave", closeAllNews);
.newstitle {
font-size: 2em;
}
.newstext {
display: none;
}
#newsblock {
max-height: 150px;
overflow: scroll;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="newsblock">
<div>
<div class="newsentry">
<div class="newstitle">News 1</div>
<div class="newstext"></div>
</div>
<div class="newsentry">
<div class="newstitle">News 2</div>
<div class="newstext"></div>
</div>
<div class="newsentry">
<div class="newstitle">News 3</div>
<div class="newstext"></div>
</div>
<!-- Etc. -->
</div>
</div>
<!-- Ignore the script below. It is just filling in the news' text. -->
<script>
$(".newstext").each(function(i, newstext){
$.get("http://baconipsum.com/api/?type=meat-and-filler&format=html¶s=5&num=" + i)
.then(function(ipsumHtml){
$(newstext).html(ipsumHtml);
});
});
</script>
Try this:
$(".newsentry, .newsblock").hover( // <-- changed
function() {
$(this).children(".newstext").stop(true,true).slideDown();
},
function() {
$(this).children(".newstext").stop(true,true).slideUp();
}
);
This makes sure the block stays open when you hover either over the header or the block itself.
Is that what you mean?
There would be a joke , if i am wrong .. what i thing just change your css as
/* not .newsblock **/
#newsblock {
height: 200px;
overflow-y: scroll;/* not auto*/
}
It will be a lot better if you use click operation instead of hover to slide down news text block because the user can accidentally hover over any of the news entry in order to reach for the scroll bar. I think you need a accordion like functionality. You can use the below code if you are fine with click instead of hover.
$(".newsentry").click(
function() {
$(".newstext").stop(true,true).slideUp();
$(this).children(".newstext").stop(true,true).slideDown();
}
);
Or use the below one to go with hover.
$(".newsentry").hover(
function() {
$(".newstext").stop(true,true).slideUp();
$(this).children(".newstext").stop(true,true).slideDown();
},
function(){}
);
This will not close the news text block until you accidentally hover over another news entry.
I am trying to create a simple tab bar for a site that has the ability to scroll for tabs that do not fit on the page. This is quite simple and does not need to have any ajax or dynamically loaded content...it simply displays all the tabs, and when you click one, it takes you to another page.
I have scoured the internet and can not seem to find anything other than:
http://www.extjs.com/deploy/dev/examples/tabs/tabs-adv.html
however this is very heavy and complicated...I am looking for a lightweight example in jquery. If anyone can help I would be grateful!
I ended up writing it myself with a div who's overflow is set to hidden. Then used the jquery below to move the tabs in the div.
$(document).ready(function()
{
$('.scrollButtons .left').click(function()
{
var content = $(".tabs .scrollable .content")
var pos = content.position().left + 250;
if (pos >= 0)
{
pos = 0;
}
content.animate({ left: pos }, 1000);
});
$('.scrollButtons .right').click(function()
{
var content = $(".tabs .scrollable .content")
var width = content.children('ul').width();
var pos = content.position().left - 250;
//var width = content.width();
if (pos <= (width * -1) + 670)
{
pos = (width * -1) + 600;
}
content.animate({ left: pos }, 1000);
});
});
My Html looked like this:
<div class="tabs">
<div class="scrollable">
<div class="content">
<ul>
<li>Tab1</li>
<li>Tab2</li>
<li>Tab3</li>
<li>Tab4</li>
<li>Tab5</li>
</ul>
</div>
</div>
<div class="scrollButtons">
<ul>
<li>
<div class="left">
</div>
</li>
<li>
<div class="right">
</div>
</li>
</ul>
</div>
</div>
I have just created a plugin myself:
Project home: http://jquery.aamirafridi.com/jst
Could you simply wrap the tabs in a DIV with overflow-x: auto set in the CSS?
I always use JQuery UI tabs as a starting point for tabs. You can customize the JQuery UI download in the download section of the website. This method should be lighter than any other implementation, if you are already using JQuery on your website.
Out of the box, the JQuery UI tabs will not give you the scrolling you desire. This I believe could be achieved by altering the CSS, but more than likely will be easier if you alter the navigation of your site (i.e. create more levels, use shorter titles).
Hope this helps