I have many bootstrap popovers on a page, but the first one, triggered by an with an id, I need to make scrollable (and have included js to make it stay open to scroll), which is trivial enough in css, but I haven't been able to make only that specific one scroll, the others do also...:
.popover-content {
max-height: 100px;
overflow-y: auto;
}
$(document).ready(function() {
$("#scrollpop").popover({ trigger: "manual" , html: true})
.on("mouseenter", function () {
var _this = this;
$(this).popover("show");
$(".popover").on("mouseleave", function () {
setTimeout(function () {
if (!$(".popover:hover").length) {
$(_this).popover("hide");
}
}, 100);
});
}).on("mouseleave", function () {
var _this = this;
setTimeout(function () {
if (!$(".popover:hover").length) {
$(_this).popover("hide");
}
}, 100);
});
});
Text Here
Is there a way to do this, without being to invasive and work for IE8/IE9 browsers?
Thank you!
I've just had a look locally, it looks like Bootstrap adds popover elements after the element in which you target your popover to be triggered on, e.g.
$('#test').popover();
<span id="test">Hello world!</span>
<!-- popover gets generated here -->
So, you can use the adjacent sibling selector in CSS to target the fact that the popover container element is a directly following sibling of the original element. You then use a .popover-content selector after that to target the child element of the popover container (your example now):
/* target .popover-content elements that are children of .popover
elements that occur directly after the #scrollpop element */
#scrollpop + .popover .popover-content {
max-height: 100px;
overflow-y: auto;
}
Edit: updated fiddle.
Related
I have one wordpress plugin which displays popup on scroll. So I have code like this:
jQuery(window).scroll(function(){
//display popup
});
I have problem with one site. The site has those css rules:
html, body {
overflow: hidden;
}
div#pageWrap {
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
So scroll event is not triggering on window and my popup doesn't work. So in this case I should set scroll event on #pageWrap div instead on window because scroll event doesn't propagate:
jQuery("#pageWrap").scroll(function(){
//display popup
});
My question is can I handle this dinamicaly. I cannot change code of my plugin for each site where I have this problem. Is possible to do something like make scroll event to propagate or to set some failback. Any idea about this will be helpful.
I can't promise that this will accommodate all edge cases, but it should take care of most of them.
JS:
jQuery.fn['any'] = function() {
return (this.length > 0);
};
if (jQuery("html").css('overflow') == 'hidden') {
if (jQuery("body").css('overflow') == 'hidden') {
var scrollElement = jQuery('*').filter(function() { return jQuery(this).css('overflow') == 'scroll'; });
if (!scrollElement.any()) {
var scrollElement = jQuery('*').filter(function() { return jQuery(this).css('overflow-y') == 'scroll'; });
jQuery(scrollElement[0]).scroll(function(){
//display popup
});
}
else {
jQuery(scrollElement[0]).scroll(function(){
//display popup
});
}
}
else {
jQuery("body").scroll(function(){
//display popup
});
}
}
else {
jQuery(window).scroll(function(){
//display popup
});
}
https://jsfiddle.net/hopkins_matt/d0gtqkat/
I don't think there's a global solution for this issue, but maybe you'll find some close solutions.
The close solution in my mind is to find the div element that has (overflow='scroll') and it's width and height are very close to the width and height of the window.
if you found more than one div like that then you need to deal with the deepest div in the DOM.
if you haven't found any div like that, then you deal with jQuery(window) instead.
I have an element, which fills the screen. Under that I have another element which does NOT fill the screen but is hidden. So you can't manually scroll to that.
The first element which is filling the screen has the following CSS properties:
header {
position: relative;
height: 100vh;
background-color: green;
}
And the second element has these CSS properties:
#content {
display: none;
position: relative;
height: 1500px;
width: 100%;
background-color: yellow;
}
I use this code to trace the scrolling:
$('header').bind("DOMMouseScroll mousewheel", function(e) {
...
});
Inside this method I check which panel is activated (by a self created boolean) and which direction I'm scrolling to, by doing this:
$('header').bind("DOMMouseScroll mousewheel", function(e) {
var wheelDelta = e.originalEvent.wheelDelta;
if (active === header && wheelDelta <= 0) {
...
}
});
Inside that if statement I give call a method that displays the #content element below it and smoothly scrolls to it, and when its done scrolling it hides the element where we have scrolled from (header). I'm using this piece of code for that:
$('body').bind("DOMMouseScroll mousewheel", function (e) {
event.preventDefault();
var wheelDelta = e.originalEvent.wheelDelta;
$('header').unbind("DOMMouseScroll mousewheel");
if (active === header && wheelDelta <= 0) {
showScrollHide(500, content, 1000, header, 250, function () {
_window.scrollTop(0);
_scrollBackBtn.fadeIn();
active = content;
});
}
});
This works perfectly, whenever I scroll down on the header element while its active. It smoothly scrolls down to the #content element under it.
There I have a button which scrolls back up the page, I have this code for it:
_scrollBackBtn.on('click', function() {
if (active === content) {
active = header;
scrollBackHide(header, content, 500, 250, function() {
window.location = '#';
});
}
});
Which also works perfectly, it scrolls back to the top of the page.
But whenever I try to scroll down again, it doesn't do anything. How does this come?
I had to add $('header').unbind("DOMMouseScroll mousewheel"); to the code, otherwise it looked very ugly in the end result.
Whenever I added $('header').stop(); in the same section, it didn't make any difference.
So my question is. How can this .bind method be used again for the same thing?
Here's a demo if you don't understand what I mean. Whenever you scroll down on the header element, and scroll back up via the button. Its not doing the same again.
You are unbinding your mousewheel handlers when they run once and then never re-binding them, so there are no event handlers in place to react to mousewheel events after you click the button. Re-binding that event handler when you click the button does the trick.
Here is a fiddle that does that and should point you in the right direction.
I pulled your mousewheel handler out into a function so we can reuse it whenever we need to bind those events:
var handleMouseWheel = function(e){
e.preventDefault();
var wheelDelta = e.originalEvent.wheelDelta;
if (active === header && wheelDelta <= 0) {
$('body').unbind("DOMMouseScroll mousewheel");
showScrollHide(500, content, 1000, header, 250, function () {
_window.scrollTop(0);
_scrollBackBtn.fadeIn();
active = content;
});
}
};
and use that to reattach an event handler when the button is clicked:
_scrollBackBtn.on('click', function () {
if (active === content) {
scrollBackHide(header, content, 500, 250, function () {
window.location = '#';
active = header;
});
$('body').bind("DOMMouseScroll mousewheel", handleMouseWheel);
}
});
I would like to add/remove a new div when the corresponding checkbox is checked/unchecked with jQuery. Here's my attempt:
<script type="text/javascript">
$(function() {
$("#form1 :checkbox#checkbox1").click(function() {
var d = document.createElement('div');
if ($(this).is(":checked")) {
$(d).addClass("newdiv")
.html("This is a new div")
.appendTo($("#mydiv"))
.hide()
.fadeIn(1000);
}
else {
//$(".newdiv").fadeOut(1000);
$(d).fadeOut(1000);
}
});
});
</script>
The fadeIn process comes out smoothly. But when I tried to fadeOut $(d) using the same methodology, it didn't work: the new generated div remained on the page. I did some research and get a work around, with $(".newdiv").fadeOut(1000); (commented in the code above), but that's not the best solution for me I think. And also I really want to know why my first attempt didn't work. Any suggestions? Thanks.
There are few changes you can make
1. No need for the selector #form1 :checkbox#checkbox1 since you have an id for the checkbox, you can just use #checkbox1
2. Create the div using jQuery instead of using createElement $('<div/>')
3. After fading out the div you need to remove it from the dom
$(function() {
$("#checkbox1").click(function() {
if ($(this).is(":checked")) {
$('<div/>').addClass("newdiv")
.html("This is a new div")
.appendTo($("#mydiv"))
.hide()
.fadeIn(1000);
}
else {
$('#mydiv .newdiv').fadeOut(function(){
$(this).remove()
})
}
});
});
Demo: Fiddle
Another solution is to have a static div which will be shown and hidden
$(function() {
var div = $('<div/>').addClass("newdiv")
.html("This is a new div")
.appendTo($("#mydiv"))
.hide();
$("#checkbox1").click(function() {
if ($(this).is(":checked")) {
div.fadeIn(1000);
} else {
div.fadeOut(1000)
}
});
});
Demo: Fiddle
jsFiddle Demo
Every time your click handler runs, you're creating a new variable d with a new element. Instead, do that before the click handler, so each instance will reference the same element. I have included other optional improvements below.
A change event is more appropriate for checkboxes. Also, notice I made your selector just #checkbox1, since that is already unambiguous and maximally specific.
To get a better visual effect, don't add the element, hide it, then fade it in. In most browsers that will show the element flicker before it appears. Instead, use a class to hide it with css: .hidden {display: none;}. You can also use fadeToggle to toggle the visibility, instead of doing if/else. clearQueue removes extra events for multiple clicks during a transition, and makes transitions appear smoother.
Finally, use jQuery to create the element:
$(function () {
var $d = $('<div>', {
"class": "hidden",
text: "This is a new div"
}).appendTo("#mydiv");
$("#checkbox1").change(function () {
$d.clearQueue()
.stop()
.fadeToggle(1000);
});
});
You better make d a jQuery object.
<script type="text/javascript">
$(function() {
$("#checkbox1").click(function() {
var d = $('<div class="newdiv"></div>');
if ($(this).is(":checked")) {
d.html("This is a new div")
.appendTo($("#mydiv"))
.hide()
.fadeIn(1000);
}
else {
d.fadeOut(1000);
}
});
});
</script>
I have some elements that, upon hover, toggle the display (none/block) of a child ul. Unfortunately, I can't transition a fade via CSS with display. Using opacity won't work either since the hover area expands onto the opacity: 0 ul, and a combo of both (transition opacity, but still toggle display) doesn't seem to work.
Is there a way to intercept the display change via Javascript, and have it fade between block and none? Are there alternate suggestions (I tried a height: 0/auto toggle too, didn't work right)? I'd prefer an intercept method than a pure JS method, in case JS is disabled or something.
If I understand you correctly. Assuming something like: <div class="nav-container"><ul></ul></div>.
You can listen for hover on the parent, since it contains the child:
var parent = document.getElementsByClassName('nav-container')[0];
var connect = function (element, event, callback) {/* I think you */};
var disconnect = function (handle) { /* can find */};
var addClass = function (element, className) { /* these elsewhere. */};
var removeClass = function (element, className) { /* ... */};
var hoverHandle = connect(parent, 'hover', function (event) {
addClass(parent, 'hovered');
if (blurHandle) {
disconnect(blurHandle);
}
});
var blurHandle = = connect(parent, 'blur', function (event) {
removeClass(parent, 'hovered');
if (hoverHandle) {
disconnect(hoverHandle);
}
});
Then in the CSS:
.nav-container > ul {
display: none;
/* do fade out */
}
.nav-container.hovered > ul {
display: block;
/* do fade in */
}
If you're using jQuery 1.7, then this'll become:
var navContainers = $('.nav-container');
navContainers.on('hover', function () {
$(this).toggleClass('hovered');
});
navContainers.on('blur', function () {
$(this).toggleClass('hovered');
});
I've created DIV.cb-toggle, when the user hovers over this div, it animates to Orange, when they hover off of this div, it animates back to gray, when the user clicks this div, it animates to blue, telling the user that it's been selected. So when it's NOT selected, it has mouseenter mouseleave animations, but when it's selected i want to unbind these events, I DO NOT want the hover event to work when it's been selected, only when it's not selected. What's the best way to do what i'm trying to accomplish? I came up with the code below but i'm pretty sure this is a horrible way to do it and i don't know what to do. thank you so much for any help.
my code:
$('.cb-toggle').toggle(function() {
$(this).animate({"background":"blue", "color":"#fff;"});
$(".cb-toggle").unbind("click.myfadee");
}, function() {
$(this).animate({"background":"gray", "color":"#fff;"});
$('.cb-toggle').trigger('mouseenter');
});
});
and I'm calling this bind:
$(".cb-toggle").bind("click.myfadee", function(){
$(".cb-toggle").mouseenter(function() {
$(this).animate({"background":"orange", "color":"#fff;"});
}).mouseleave(function() {
$(this).animate({"background":"gray", "color":"#fff;"});
});
});
I need to keep the background color animation, it needs to fade.
I would use CSS for the styling to simplify your whole setup without un/re-binding, like this:
.cb-toggle { background: blue; color: #fff; }
.cb-toggle.active { background: gray; }
.cb-toggle.active:hover { background: orange; }
Then you can do just this:
$('.cb-toggle').click(function() {
$(this).toggleClass("active");
});
This approach also lets you offload all styling, colors, etc to the CSS, meaning no JavaScript changes are needed when you decide to tweak the colors or any other styling :)
Or, if you need to support IE6, add a .live() handler for the hover that triggers on only the ones with the .active class, like this:
$(".cb-toggle.active").live('mouseenter', function() {
$(this).addClass('hover');
}).live('mouseleave', function() {
$(this).removeClass('hover');
});
With matching CSS:
.cb-toggle.active.hover { background: orange; }
You should probably just use a selected class. Also I'd recommend against using any of the .css() calls you have here. Just use classes.
$(".cb-toggle").bind("click.myfadee", function(){
$(this).toggleClass('selected');
});
$('.cb-toggle').toggle(function() {
var $this = $(this);
if ( $this.is('.selected') ) {
$this.css({"background":"blue", "color":"#fff;"});
}
}, function() {
var $this = $(this);
if ( $this.is('.selected') ) {
$this.css({"background":"gray", "color":"#fff;"});
}
});