Detect scroll-event on every parent-element - javascript

I have a directive which should detect a scroll-event on every parent element. The scrollable element could be div with overflow:scroll or the browser-window itself. So this solution does not work in all cases:
angular.element($window).bind("scroll", function() { ... });

You need to listen for the scroll event at the capture phase. To do this, pass true as the third parameter of addEventListener:
document.getElementById('parent').addEventListener('scroll', () => {
console.log('scrolling');
}, true);
Your example works when I replace your javascript with the code above, and there's no jQuery dependancy.

You need to add some specific height for the div elements to scroll
For example:
div{
height: 350px; // Specify div height as you want
overflow: scroll;
}

Okay, I found the solution. Here it is:
angular.element(document.querySelectorAll('*')).bind("scroll", $scope.myFunction);

Related

jQuery not detecting div resize [duplicate]

This question already has answers here:
How to detect DIV's dimension changed?
(28 answers)
Closed 7 years ago.
UPDATE: since everyone is hung up on window resize
I've got a div inside a resizable div and I want to detect the resize of the child div. I know .on('resize') is only for the window. My question is solely based on the child div resize.
<div id='main_wrapper'>
<div id = 'child_div'>
</div>
</div>
html,
body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
}
#main_wrapper {
height: 300px;
width: 300px;
background-color: blue;
}
#child_div{
height: 100%;
width: 100%;
}
$('#main_wrapper').resizable();
$('#child_div').on('resize', function() { //i know this isn't proper, how to do this is my question.
alert('i changed');
})
https://jsfiddle.net/cyclingpaper/2kksqoLs/
Thanks for your time.
The resize event is only targetted by the window object. You can't attach it to another DOM tree element than the most top.
https://developer.mozilla.org/en-US/docs/Web/Events/resize
Here you go:
https://jsfiddle.net/danhaswings/ejoxphov/2/
You can't bind the resize event to anything other than the window.
// cache objects
var $main_wrapper = $('#main_wrapper');
// on window resize
$(window).resize(function() {
console.log('The window has resized.');
// random example to run on window resize
$main_wrapper.css({
'background-color': 'red'
});
});
Post Edited: Downvoters please remove the downvotes for no reason / anger!
The resize event is for window only, not for elements. Use this code instead:
$(window).on('resize', function(){
alert('i changed');
});
Fiddle: https://jsfiddle.net/effsmpdm/
Take a look at this
http://benalman.com/code/projects/jquery-resize/examples/resize/
It has various examples. Try resizing your window and see how elements
inside container elements adjusted.
Example with js fiddle to explain how to get it work. Take a look at this fiddle
http://jsfiddle.net/sgsqJ/4/
In that resize() event is bound to an elements having class "test" and
also to the window object and in resize callback of window object
$('.test').resize() is called.
e.g.
$('#test_div').bind('resize', function(){
console.log('resized');
});
$(window).resize(function(){
$('#test_div').resize();
});
Source: How to detect DIV's dimension changed?

How to scroll window without overflow

I need to scroll in a window but my window height is too small to scroll. Is it possible to scroll when the height of container is too small to see the scrollbar.
Here is my code to scroll:
setTimeout(function(){
$(window).scrollTop($(window).scrollTop()+1);
$(window).scrollTop($(window).scrollTop()-1);
}, 800);
I need to scroll window or body even if height of it is less than 100px.
I believe you want to set a min-height of 110% on html in your CSS. I would do:
html {
min-height: 110%;
}
Here's a demo: http://jsbin.com/sebago/1/edit?html,css,output
If you define a fixed height in your element, then you can use overflow:scroll to enable scroll.
You need first hide the scroll bar to do not take space (because you don't have too much space in the element), you can make that with the next css:
#elementId{
overflow: hidden;
}
Then you need to bind the mousewheel event over the 'small' element and trigger a function to manually scroll your element, you can do that with the next jQuery code:
$('#elementId').bind('DOMMouseScroll mousewheel', function(e) {
$('#elementId').scrollTop($('#elementId').scrollTop()+1);
});
This example is simplified just to bind the mousewheel event in general, to know if it is up or down you can use the jQuery Mouse Wheel Plugin that you can get here.
To see scrollbar, just use CSS property overflow:scroll; on your container.

Highlight an element on hover

I want to highlight an element on hover, and only that element.
This should mimic the behaviour of hovering over an element with chrome dev tools when you have the magnifying glass selected.
It's for a chrome extension I'm making.
I think I need a JS solution, as the pseudo :hover in css seems to apply to all elements in the background, i.e. container elements, so I'd need to prevent event bubbling in css, which as far as I can tell you can't do.
I have tried
$('body').children().mouseover(function(e){
$(".hova").removeClass("hova");
$(this).addClass("hova");
}).mouseout(function(e) {
$(this).removeClass("hova");
});
-css-
.hova {
background-color: pink;
}
and jquery's hover(), both always selects the container too.
I have also tried with css opacity, incase the background was covered, but it seems it always selects the parent element. I want the furthest child down the DOM that I am hovering over.
I'm sure there's some simple solution out there, maybe its over complicating as its in a chrome extension... I'm not sure
Is this what you need? http://jsbin.com/vidojamece/1/
Instead of adding the class to $(this) inside the handler, add the class to e.target (span) and return false so it doesn't bubble up to the div:
$('body').children().mouseover(function(e){
$(".hova").removeClass("hova");
$(e.target).addClass("hova");
return false;
}).mouseout(function(e) {
$(this).removeClass("hova");
});
You need to use the target element instead of 'this', which is the actual element that you hover over and use stopPropagation in order to not repeat the process for each element behind:
$('body').children().mouseover(function(e){
e.stopPropagation();
$(".hova").removeClass("hova");
$(e.target).addClass("hova");
}).mouseout(function(e) {
$(e.target).removeClass("hova");
});
You can do this with css (and js too):
*:hover {
background-color: pink;
}
or even
div:hover {
background-color: pink;
}
In js:
$('body').children().each(function() {
$(this).hover(function() {
$(".hova").removeClass("hova");
$(this).addClass("hova");
}, function() {
$(this).removeClass("hova");
});
});

JS launches before CSS

This is currently happening in chrome, in firefox I haven't had this issue (yet).
Here is a VERY simplified version of my problem.
HTML:
<div class="thumbnail">
Click me!
</div>
CSS:
div {
width: 200px;
height: 300px;
background-color: purple;
}
a {
position: absolute;
}
#media (max-width: 991px) {
div {
height: 200px;
}
}
Javascript:
$(document).ready(function () {
var $parent = $('#clickMe').parent();
function resize() {
$('#clickMe').offset({
top: $parent.offset().top + $parent.height()-$('#clickMe').height()
});
}
$(window).on('resize', resize);
resize();
});
The problem:
So what does this give when I resize (without dragging)? Well javascript launches first and sets the position of the <a></a> , then CSS applies the height change if we are < 992 px.
Logically the button is now visually at the outside of the div and not on the border like I had originally defined it to be.
Temporary solution proposed in this post.
jQuery - how to wait for the 'end' of 'resize' event and only then perform an action?
var doit;
$(window).on('resize', function(){ clearTimeout(doit); doit = setTimeout(resize, 500); });
Temporary solution is not what I'm looking for:
However, in my situation I don't really need to only call 'resize' when the resizing event is actually done. I just want my javascript to run after the css is finished loading/ or finished with it's changes. And it just feels super slow using that function to 'randomely' run the JS when the css might be finished.
The question:
Is there a solution to this? Anyone know of a technique in js to wait till css is completely done applying the modifications during a resize?
Additional Information:
Testing this in jsfiddle will most likely not give you the same outcome as I. My css file has many lines, and I'am using Twitter Bootstrap. These two take up a lot of ressources, slowing down the css application (I think, tell me if I'm wrong).
Miljan Puzović - proposed a solution by loading css files via js, and then apply js changes when the js event on css ends.
I think that these simple three steps will achieve the intended behavior (please read it carefully: I also suggest to read more about the mentioned attributes to deeply understand how it works):
Responsive and fluid layout issues should always be primarily (if not scrictly) resolved with CSS.
So, remove all of your JavaScript code.
You have positioned the inner a#clickMe element absolutely.
This means that it will be positioned within its closest relatively positioned element. By the style provided, it will be positioned within the body element, since there is no position: relative; in any other element (the default position value is static). By the script provided, it seems that it should be positioned within its direct parent container. To do so, add position: relative; to the div.thumbnail element.
By the script you provided, it seems that you need to place the a#clickMe at the bottom of div.thumbnail.
Now that we are sure that the styles added to a#clickMe is relative to div.thumbnail, just add bottom: 0px; to the a#clickMe element and it will be positioned accordingly, independently of the height that its parent has. Note that this will automatically rearrange when the window is resized (with no script needed).
The final code will be like this (see fiddle here):
JS:
/* No script needed. */
CSS:
div {
width: 200px;
height: 300px;
background-color: purple;
position: relative; //added
}
a {
position: absolute;
bottom: 0px; //added
}
#media (max-width: 991px) {
div {
height: 200px;
}
}
If you still insist on media query change detection, see these links:
http://css-tricks.com/media-query-change-detection-in-javascript-through-css-animations/
http://css-tricks.com/enquire-js-media-query-callbacks-in-javascript/
http://tylergaw.com/articles/reacting-to-media-queries-in-javascript
http://davidwalsh.name/device-state-detection-css-media-queries-javascript
Twitter Bootstrap - how to detect when media queries starts
Bootstrap: Responsitive design - execute JS when window is resized from 980px to 979px
I like your temporary solution (I did that for a similar problem before, I don't think half a second is too long for a user to wait but perhaps it is for your needs...).
Here's an alternative that you most likely have thought of but I don't see it mentioned so here it is. Why not do it all through javascript and remove your #media (max-width.... from your css?
function resize() {
var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
if(width<992){
$("div").each(function(e,obj){$(obj).height(200);});
}
$('#clickMe').offset({
top: $parent.offset().top + $parent.height()-$('#clickMe').height()
});
}
In the html page, put the link to css file in head section; next, put the link to js file just before the /body tag and see what happens. In this way css will load always before js.
Hope this help you.
Did you try to bind the resize handler not to the window but to the object you want to listen to the resize ?
Instead of
$(window).on('resize', resize);
You can try
$("#clickMe").on('resize', resize);
Or maybe
$("#clickMe").parent().on('resize', resize);
var didResize = false;
$(window).resize(function() {
didResize = true;
});
setInterval(function() {
if (didResize) {
didResize = false;
console.log('resize');
}
}, 250);
I agree with falsarella on that you should try to use only CSS to do what you are trying to do.
Anyway, if you want to do something with JS after the CSS is applied, I think you can use requestAnimationFrame, but I couldn't test it myself because I wasn't able to reproduce the behavior you explain.
From the MDN doc:
The window.requestAnimationFrame() method tells the browser that you
wish to perform an animation and requests that the browser call a
specified function to update an animation before the next repaint. The
method takes as an argument a callback to be invoked before the
repaint.
I would try something like this:
var $parent = $('#clickMe').parent();
function resize(){
$('#clickMe').offset({
top: $parent.offset().top + $parent.height()-$('#clickMe').height()
});
}
window.onresize = function(e){
window.requestAnimationFrame(resize);
}
window.requestAnimationFrame(resize);
Anyone know of a technique to wait till css is completely done loading?
what about $(window).load(function() { /* ... */ } ?
(it executes the function only when the page is fully loaded, so after css loaded)

Show and Hide a DIV with CSS or Javascript?

I just saw a demo that had this jquery code to show and hide a dive on hover, can't this be done with just regualr css though? And if you can do it with css is there any advantage of doing it with javascript?
$('.comment').hover(function() {
$(this).children('.delete').show();
}, function() {
$(this).children('.delete').hide();
});
CSS hover works fine with anchor tags, but IE6 does not recognize hover events on things like li tags.
If you were using an anchor tag, however, you could achieve the same effect in CSS:
a.comment .delete { display: none; }
a.comment:hover .delete { display: block; }
You can do this with CSS but IE6 only supports the :hover pseudo-class on anchor tags (A), so it's not as common.
Jody is correct. Check out the docs for the CSS Display property.
There is more functionality that the .hover will do. If you provide it more than 2 functions it will cycle through all the functions.
Example
$('.comment').hover(
function(){$(this).children('.delete.first').show()},
function(){$(this).children('.delete.first').hide()},
function(){$(this).children('.delete.second').show()},
function(){$(this).children('.delete.second').hide()}
);
That would show one set of children the first time they hover, then hide, and the next time show a different set of children.
The hover function also works over multiple elements, and only fires if the mouse has left all the elements (not just when it leaves one and moves to another)
I dynamically create something like this on the server side. I'm sure there is a more efficient/prettier way but this usually serves my needs. Basically hides all the divs and un-hides the one that needs to be shown (passed as arg in function from onClick event).
function toggleTab(id)
{
document.getElementById('divEnrollment').style.display='none';
document.getElementById('divSearch').style.display='none';
document.getElementById('divMeeting').style.display='none';
document.getElementById('divBenefit').style.display='none';
document.getElementById('div' + id).style.display='block';
document.getElementById('spnEnrollment').style.color='blue';
document.getElementById('spnSearch').style.color='blue';
document.getElementById('spnMeeting').style.color='blue';
document.getElementById('spnBenefit').style.color='blue';
document.getElementById('spn'+id).style.color = 'red';
}

Categories