Now, I want to make fade from top effect when my element be in the viewport by adding 'activate' class for it...
I don't want to use any external libraries that do it direct.
My code is:
window.addEventListener('scroll', function(e) {
var cards = document.querySelectorAll('cards');
for ( let card of cards ) {
if(!card.classList.contains('fadeFromTop')) {
card.classList.add('fadeFromTop');
}
}
}
but when my element goes out from the viewport, it still checks if the element has that class
I didn't add the if statement that checks if the element is inside the viewport.
Is there a way to break and stop the scroll event when all cards have the class 'fadeFromTop' ?
I tried to search on google but what I find is the element.removeEventListener(); and I can't understand what does it do...
Related
I need to trigger an event on a class when that class changes
The only known change noticed in the DOM is that the class obtains a second class (say the class is "selectable", it becomes "selectable selected")
https://jsfiddle.net/zn1xj7wb/1/
In this fiddle, the blue squares may be selected and the css change happens when the class changes (adds "selected")
The goal is to be able to do something in another part of my code like that:
$("[class*='selectable']").on('classChange', function() {
//do stuff like change the background color or add text
//alert("this selectable div has been selected");
});
I am unsure how to proceed as jquery has no event for a class change, and I cannot add "classChange" the trigger to the hidden part of the code that adds and removes the "selected" class for it to be picked up by my code.
EDIT: the reason I need the trigger to be the class change is that it is a graph that uses up the first click to change the class (select the node of the graph) and so a first click on the div of that class does not register, only the second time, and I cannot have to click twice to //do stuff.
I'm not sure I understand your problem, but what I would do is atach the event to the document, like this:
$(document).on("click",".selectable", function() {
//do your stuff here
});
Now, as I've read you need to do something right after you add the class "selected" to "selectable", so you could do it in the function by checking wether it has the class or not and then do your stuff after you add the class "selected".
$(document).on("click",".selectable", function() {
if($(this).hasClass("selected")){
$(this).removeClass("selected")
//do your stuff
}else{
$(this).addClass("selected")
//do some different stuff
}
});
EDIT: Okay, so that won't work (see comments). However, I was able to come up with another solution. While you could regularly scan the whole DOM for changes using an external library, in this instance, you can make the app more performant by limiting your scope to just the selectable items.
What the following code does (jsfiddle link below) is take an initial sampling of the selected elements on the page. Then, once per event loop, it re-samples those selected elements. For each element that wasn't there before, it triggers a custom event:
$(document).ready(function() {
$('.selectable').on('customSelectEvent', (e) =>{
console.log("hello, world!");
// Do your stuff here
});
// Get the starting list of selectable elements
var selecteds = $('.selected');
// Using setInterval to make sure this runs at the back of the event loop
setInterval(() => {
let loopSelecteds = $('.selected');
$.each(loopSelecteds, function(loopIndex, loopSelected) {
let alreadySelected = false;
$.each(selecteds, function(index, selected) {
if ($(selected).get(0) === $(loopSelected).get(0)) {
alreadySelected = true;
}
});
if (!alreadySelected) {
$(loopSelected).trigger('customSelectEvent');
}
});
selecteds = loopSelecteds;
}, 0);
})
Some things to note here:
setInterval(()=>{...}, 0) is being used to cast this operation to the back of the event loop, so it will evaluate once per turn. Use caution when doing this, because if you do it too much, it can impact performance.
$().get(0) === $().get(0) is testing the DOM elements to see if they are the same element. We don't want to trigger the event if they are. Credit: https://stackoverflow.com/a/19546658/10430668
I'm using $.each() here because it's intelligent enough to handle collections of jQuery objects, which other loops weren't (without some fiddling).
Someone spot check me on this, but you may be able to put the custom event listener elsewhere in the code.
JS Fiddle: https://jsfiddle.net/zn1xj7wb/15/
This is my first answer, which doesn't work in this use case. I'll include it so that users who aren't so stuck can benefit from it:
Is there any reason you can't bind another listener to the click event
and test if it's got the right class? Such as:
$(document).ready(function() {
$(".selectable").click((e) => {
const currentElement = $(e.currentTarget);
// This is a little tricky: don't run the code if it has the class pre-setTimeout()
if (currentElement.hasClass('selected')) {
return;
}
// Using setTimeout to cast the evaluation to the end of the event loop
setTimeout(()=>{
if (currentElement.hasClass('selected')) {
// Do your things here.
alert("selected!");
}
},0);
})
})
I'm having issues combining ng-swipe and horizontal scrolling on mobile. The use case is that I have a page that on swiping should load next or previous and inside there are modules that show a lot of information. Some of it is scrolled.
So, as soon as you scroll the swipe on the parent kicks in and you get navigated. So I put another pair of ng-swipe on the parent of the scrollable element with this sort of trickery:
self.onInnerSwipe = function($event) {
$event.originalEvent.preventAction = true;
};
And then on the parent:
var shouldActionProceed = function($event) {
return !$event || !$event.originalEvent || !$event.originalEvent.preventAction;
};
self.goToPrev = function($event) {
if (shouldActionProceed($event)){
// Do Magic
}
}
This does the trick in the way that the action doesn't proceed if I'm swiping over that element but the scroll doesn't really work. It sorts of but it doesn't. It starts a bit and then stops.
On Chrome there are this warnings being logged sometimes.
Ignored attempt to cancel a touchmove event with cancelable=false, for
example because scrolling is in progress and cannot be interrupted.
I have prepared a demo here: http://jsbin.com/webologavu/2/ which is overly simplistic but you can reproduce the issue.
Any hints?
I think that it's a concurrency issue with these events. It might work better if you your parent event doesn't rely on the child event. To achieve that:
//add a identifier to your list element
<ul class="myList" your-other-attrs></ul>
//should proceed can rely on the target element to find out
//if the target element belongs (or is) in your list.
var shouldActionProceed = function($event) {
return !$($event.target).hasClass("myList") && //is myList?
$($event.target).parents(".myList").length == 0; //has parent 'myList'?
};
This way, the parent event can work on its on.
I have two separate elements in my DOM that require a change when either one is hovered. When the link is hovered, the image src needs to change (easy) AND the link color needs to change. When the image is hovered, the same effect needs to happen (image src changes & link color changes)
This is actually quite easy to do, but I have a feeling there is a MUCH easier way to do it then the approach I am taking. Currently I am going through each of the 8 elements and testing if they are hovered individually. This works good, but there is so much more jQuery here than I feel there should be.
I tried adding the attribute onmouseover to both of the elements and triggering the same function, but for some reason the function wasn't triggering.
Is there a way to test if either element is hovered and trigger a function if either one is? Something like this:
if($(#elm1).hover() || $('#elm2').hover()) {
//effect here
}
OR
if($('#elm1').is(':hover') || $('#elm2').is(':hover')) {
//effect here
}
I tried my example code above, but wasn't getting any results. Is there a way to do this or am I stuck with checking each individual element?
It works, you're just running it on page load, not when the mouse moves
$(document).mousemove(function() {
if($('#elm1').is(':hover') || $('#elm2').is(':hover')) {
// Do stuff
}
else {
// Revert do stuff or do other stuff
}
});
Example here
But, as other's have said, jQuery already knows the hover state, so doing it this way would be unnecessary. In practice you should use the same selector to apply the function to it
$('#idOne, #idTwo').hover(function() { /* Do stuff */ });
I would register events on mouseover and whenever the event happens trigger a function
$("#elm1, #elm2").on("mouseover", function () {
// effect here
});
Why not simply add the handler to both elements like this :
$('#elm1, #elm2').hover(function(){
// ... do stuff here ...
});
Should work . . .
In Masonry, it is possible to delete an element by clicking on it. The catch is, that You have to click directly on that element - so if you use these "bricks" as an image gallery (as long as these photos are included as a background image) You can delete them, by clicking on the element. The problem is, when you use these as some messages/info/other content containers. Then, due to formatting-related stuff the parent element gets "hidden" behind other tags, and You can't actually click on it.
The problem is shown here:
http://jsfiddle.net/dan1410/SfU5T/
You can close red boxes, but not green ones, as they are overlapped by another elements.
I've tried code like:
eventie.bind( container, 'click', function( event ) {
// don't proceed if item was not clicked on
if ( !classie.has( event.target, 'closeable' ) ) {
return;
}
// remove clicked element
msnry.remove( event.target );
// layout remaining item elements
msnry.layout();
});
});
and
var todelete = document.querySelector('.closeable');
eventie.bind( container, 'click', function( event ) {
// remove clicked element
msnry.remove( todelete );
// layout remaining item elements
msnry.layout();
});
});
but You still have to click directly on the element You'd like to close...
My masonry content structure looks like
<div id="masonry" >
<div class="item blue closeable">
<div id="itheader"><h2 class="secsectiontitle">Space available</h2></div>
<div id="itcontent">
some statistics here...<br/>
and here, too
</div>
</div>
Only elements with .closeable class are supposed to be closeable.
So, the question is: how to close an element using a button/a link?
I'm not very familiar with JS, so I'd like to ask You guys for help. Thank You in advance!
Unless there are handlers that stops the propagation of the click event on children elements, the click event should bubble up without any issues.
Also, if you are using jQuery, you should use the jQuery Masonry's API.
Note: I couldn't access your fiddle and couldn't test the solution
var $container = $('#masonry').on('click', '.closeable', function (e) {
$container.masonry('remove', e.currentTarget);
$container.masonry(); //layout
$container.masonry('reloadItems'); //OP said it was also required
});
I want to detect if is not visible in browser window for an interactive map i am building. if the div is not visible I will show a popup saying "this way" or something like that. The main issue is detecting when the div is not visible in the document window.
What I gather from your question is you want to detect if a div can be seen on the visible portion of the screen, NOT whether it's visible based upon its CSS (display, visibility).
If so, you need to determine the div's offset, then check if that's within the bounds of either the document dimensions, or another element's dimensions.
Something like this (assuming you're using jQuery)...
var div_offset = $('#div').offset();
if( div_offset.top < $(document).height() &&
div_offset.left < $(document).width() ) {
// div is within window bounds
}
This is a very basic example. You would of course need to factor in how much of the div element you would want to showing for it to be considered "visible"... the above code would be true even if only the single top/left pixel of the div sits within the document bounds. Do this by perhaps testing if the bottom right corner is showing by adding the width/height to the offset.
You can check as follows:
if (document.getElementById("myDiv").style.visibility == 'hidden'){
//
}else{
//
}
you can also use like this without "is"
// check if div is visible
$("div:visible").click(function () {
alert("hello to all");
});
// check if div is hidden
$("div:hidden").show("fast");
You can use is function with :visible
Live Demo
if($('#divId').is(':visible'))
{
alert("div is visible");
}
else
{
alert("div is not visible");
}
or
if($('#divId :visible').length)
{
alert("div is visible");
}
else
{
alert("div is not visible");
}
If you want to check if the element is visible in viewport you can use InView
Install it with npm :
npm install #opuu/inview
Use it like this :
// import it
import InView from "#opuu/inview";
// select elements to track
let elements = new InView(".selector");
// add enter event listener
elements.on("enter", (event) => {
console.log(event);
// do something on enter
});
// add exit event listener
elements.on("exit", (event) => {
console.log(event);
// do something on exit
});
Note: I wrote this package.