Firing events in Twitter Bootstrap's Carousel - javascript

Once the carousel has slid, I want to add a value to an input outside of the ID myCarousel.
The function to implement an event once the carousel has slid is this:
$('#myCarousel').bind('slid', function() {
$('input[name=linkOnly]').val('Test')
}
I want to fire an event once a particular slide slides. I've tried something like $('#myCarousel li[data-slide-to=1]').bind('slid', function() ... but it doesn't register.
Any help appreciated, thanks.

You could just setup an event handler on the appropriate event and then choose to do anything based on which slide is .current. For example, to trigger some javascript when slide 1 cycles in:
$(document).on("slid", function(event) {
if ($(event.target).find(".active").data("slide-to") == 1) {
// do stuff
}
});
From a quick test, this doesn't seem to work unless it attached to an element above the carousel (you'd also need to change things a little if you had more than one carousel).
EDIT: After a quick look, the reason the above doesn't work if bound to the carousel itself is that the active class isn't added until immediately after the slid event is triggered (it seems that if the handler is added to a parent element, the active class gets added while the slid event bubbles up). You can get around this by using setTimeout to delay the triggered behaviour (works even with a timeout of 0):
$("#myCarousel").on("slid", function(event) {
var carousel = $(event.target);
setTimeout(function() {
if (carousel.find(".carousel-indicators .active").data("slide-to") === 1) {
// do stuff
}
}, 0);
});
Whether the extra code is worth it is up to you, although it may be a little more stable. It may even be worth putting in a small delay (instead of 0), just to make sure that things do work the way you expect them to.

Related

Remove touchpointer in javascript

I was trying to make a webapp with html elements that will move form div to antoher div when clicked but also I want to be able fire event when users hold that element for more than a second. So I have this code
$(document).on("click",'.card', function() {
var card=$(this).parent();
if(card.parent().attr('id')==="options"){
card.appendTo("#choice");
}
else{
card.appendTo("#options");
}
});
var timeoutId = 0;
$('.card').on('pointerdown', function() {
timeoutId = setTimeout(showModal, 1000);
}).on('pointerup mouseleave', function() {
clearTimeout(timeoutId);
});
And it is doing almost fine. The problem occures when the element is clicked. It is appended to different div as it should but the mobile pointer is still on it so when I try to fire 'hold' event on another element it is not working for the first time since 'pointerup' event from previous element is firing right after 'pointerdown' event (So you need to try to hold next element twice).
I've dealt with it by adding a simple boolean flag in click event function so it is blocking next first call of 'pointerup' event but this is a very ugly solution.
Do you have any ideas how can i improve this? Maybe there is a way to call 'pointerup' event manually after click?
Removing 'mouseleave' event and adding 'pointerleave' instead fixed the problem.
Not really sure how 'mouseleave' event was fired on mobile device though.

How to unbind() .hover() but not .click()?

I'm creating a site using Bootstrap 3, and also using a script that makes the dropdown-menu appear on hover using the .hover() function. I'm trying to prevent this on small devices by using enquire.js. I'm trying to unbind the .hover() event on the element using this code:
$('.dropdown').unbind('mouseenter mouseleave');
This unbinds the .hover of that script but apparently it also removes the .click() event(or whatever bootstrap uses), and now when I hover or click on the element, nothing happens.
So I just want to how I can remove the .hover() on that element, that is originating from that script, but not change anything else.
Would really appreciate any help.
Thanks!
Edit: Here is how I'm calling the handlers for the hover functions:
$('.dropdown').hover(handlerIn, handlerOut);
function handlerIn(){
// mouseenter code
}
function hideMenu() {
// mouseleave code
}
I'm trying to unbind them with this code.
$('.dropdown').unbind('mouseenter', showMenu);
$('.dropdown').unbind('mouseleave', hideMenu);
But its not working.
Please help!
**Edit2: ** Based on the answer of Tieson T.:
function dropdownOnHover(){
if (window.matchMedia("(min-width: 800px)").matches) {
/* the view port is at least 800 pixels wide */
$('.dropdown').hover(handlerIn, handlerOut);
function handlerIn(){
// mouseenter code
}
function hideMenu() {
// mouseleave code
}
}
}
$(window).load(function() {
dropdownOnHover();
});
$(window).resize(function() {
dropdownOnHover();
});
The code that Tieson T. provided worked the best; however, when I resize the window, until I reach the breakpoint from any direction, the effect doesn't change. That is, if the window is loaded above 800px, the hover effect will be there, but if I make the window smaller it still remains. I tried to invoke the functions with window.load and window.resize but it is still the same.
Edit 3: I'm actually trying to create Bootstrap dropdown on hover instead of click. Here is the updated jsFiddle: http://jsfiddle.net/CR2Lw/2/
Please note: In the jsFiddle example, I could use css :hover property and set the dropdow-menu to display:block. But because the way I need to style the dropdown, there needs to be some space between the link and the dropdown (it is a must), and so I have to find a javascript solution. or a very tricky css solution, in which the there is abot 50px space between the link and the dropdown, when when the user has hovered over the link and the dropdown has appeared, the dropdown shouldn't disappear when the user tries to reach it. Hope it makes sense and thanks.
Edit 4 - First possible solution: http://jsfiddle.net/g9JJk/6/
Might be easier to selectively apply the hover, rather than try to remove it later. You can use window.matchMedia and only apply your script if the browser has a screen size that implies a desktop browser (or a largish tablet):
if (window.matchMedia("(min-width: 800px)").matches) {
/* the view port is at least 800 pixels wide */
$('.dropdown').on({
mouseenter: function () {
//stuff to do on mouse enter
},
mouseleave: function () {
//stuff to do on mouse leave
}
});
}
else{
$('.dropdown').off('mouseenter, mouseleave');
}
Since it's not 100% supported, you'd want to add a polyfill for those browsers without native support: https://github.com/paulirish/matchMedia.js/
If you're using Moderizr, that polyfill is included in that library already, so you're good-to-go.
I still don't understand how you intend to "dismiss" the dropdown-menu once it is displayed upon mousing over the dropdown element partly because there's not enough code in your question, but that's sort of irrelevant to this answer.
I think a much easier way to approach the mousenter event handling portion is not by using off()/on() to unbind/bind events at a specific breakpoints, but rather to do just do a simple check when the event is triggered. In other words, something like this:
$('.dropdown').on('mouseenter', function() {
if($('.navbar-toggle').css('display') == 'none') {
$(this).children('.dropdown-menu').show();
};
});
$('.dropdown-menu').on('click', function() {
$(this).hide();
});
Here's a working fiddle: http://jsfiddle.net/jme11/g9JJk/
Basically, in the mouseenter event I'm checking if the menu toggle is displayed, but you can check window.width() at that point instead if you prefer. In my mind, the toggle element's display value is easier to follow and it also ensures that if you change your media query breakpoints for the "collapsed" menu, the code will remain in sync without having to update the hardcoded values (e.g. 768px).
The on click to dismiss the menu doesn't need a check, as it has no detrimental effects that I can see when triggered on the "collapsed" menu dropdown.
I still don't like this from a UX perspective. I would much rather have to click to open a menu than click to close a menu that's being opened on a hover event, but maybe you have some magic plan for some other way of triggering the hide method. Maybe you are planning to register a mousemove event that checks if the mouse is anywhere within the bounds of the .dropdown + 50px + .dropdown-menu or something like that... I would really like to know how you intend to do this (curiosity is sort of killing me). Maybe you can update your code to show the final result.
EDIT: Thanks for posting your solution!

Am I binding events over and over again in this jQuery code?

So I used this totally awesome tool called Visual Event, which shows all the event handlers bound to an object - and I noticed that every time I clicked or played around with my object and checked the list of event handlers bound to it, there were and more every time. My problem is this one: console.trace or stack trace to pinpiont the source of a bug in javascript? After using Visual Event and someone else's suggestion, I'm thinking my problem is that I'm probably binding the same handlers to the same events over and over again. Is there a way to unbind things regularly?
My application has a bunch of plugins connect to dynamically created divs. These divs can be resized and moved around the place. The application is a kind of editor, so users arrange these divs (which contain either images or text) in any design they like. If the user clicks on a div, it becomes "activated", while all other divs on the page get "deactivated". I have a bunch of related plugins, like activateTextBox, initTextBox, deactivateTextBox, readyTextBox, and so on. Whenever a div is first created, the init plugin is called once, just the first time after creation, like so:
$(mydiv).initTextBox();
But readyTextBox and activateTextBox and deactivateTextBox are called often, depending on other user events.
In init, I first use bind things like resizable() and draggable(), then I make the box "ready" for use
$.fn.extend({
initTextBox: function(){
return this.each(function() {
// lots of code that's irrelevant to this question
$this.mouseenter(function(){
if(!$this.hasClass('activated'))
$this.readyTextBox();
}
$this.mouseleave(function(){
if($this.hasClass('ready')){
$this.deactivateTextBox();
$this.click(function(e){
e.preventDefault();
});
}
});
});
});
Here's a simplified summary version of the readyTextBox plugin:
(function($){
$.fn.extend({
readyTextBox: function(){
return this.each(function() {
// lots of code that's irrelevant to this question
$this.resizable({ handles: 'all', alsoResize: img_id});
$this.draggable('enable');
$this.on( "dragstop", function( event, ui )
{/* some function */ });
$this.on("resizestop", function( event, ui ){ /* another function */ });
// and so on
});
Then there's activateTextBox():
$.fn.extend({
activateTextBox: function(){
return this.each(function() {
// lots of code that's irrelevant to this question
$this.resizable('option','disabled',true); //switch of resize & drag
$this.draggable('option', 'disabled', true);
});
Then deactivate, where I turn on draggable and resizable again, using the code:
$this.draggable('enable'); $this.resizable('option','disabled',false);
These divs, or "textboxes" are contained within a bigger div called content, and this is the click code I have in content:
$content.click(function(e){
//some irrelevant code
if( /* condition to decide if a textbox is clicked */)
{ $(".textbox").each(function(){ //deactivate all except this
if($(this).attr('id') != $eparent.attr('id'))
$(this).deactivateTextBox();
});
// now activate this particular textbox
$eparent.activateTextBox();
}
});
This is pretty much the relevant code related to text boxes. Why is it that whenever I drag something around and then check Visual Event, there are more clicks and dragstops and mouseovers than before? Also, the more user interacts with the page, the longer the events take to complete. For example, I mouseout from a div, but the move cursor takes a loooong time to get back to default. I quit dragging, but everything gets stuck for a while before getting ready to take more user clicks, etc. So I'm guessing the problem has to be that I'm binding too many things to the same events need to be unbinding at some point? It gets so bad that draggable eventually stops working at some point. The textboxes just get stuck - they're still able to be resized, but dragging stops working.
Am I binding events over and over
Yes. Have a look at your code:
$this.mouseenter(function(){
…
$this.mouseleave(function(){
…
$this.click(function(e){
…
});
});
});
That means every time you mouseover the element, you add another leave handler. And when you leave the element, every of those handlers adds another click event.
I'm not sure what you want to do, but there are several options:
bind the event handlers only once, and keep track of the current state with boolean variables etc.
before binding, remove all other event handlers that are already bound. jQuery's event namespacing can help you to remove only those which your own plugin added.
use the one() method that automatically unbinds a listener after firing it.

JQuery Animation Queue Never Stops

I have created a simple drop-down menu with JQuery, following a tutorial. LINK :
http://wabism.com/development/jquerydropdown/
Its jQuery code is this:
$('body').ready(function() {
// Add the 'hover' event listener to our drop down class
$('.dropdown').hover(function() {
// When the event is triggered, grab the current element 'this' and
// find it's children '.sub_navigation' and display/hide them
$(this).find('.sub_navigation').slideToggle();
});
});
Drop-down works fine with 1 error. If you rollover and out a menu item 3 or 4 times quickly, it does all the 3 or 4 slidetoggle() 's. How can I overcome this problem ?
Use .stop() method before animation.
As you described, animations in jQuery would be queued and all of them would be executed, unless you explicitly specify that you want any pending animation to stop. You would do this using .stop() function. In your case you should write:
$(this)
.find('.sub_navigation')
.stop()
.slideToggle();
It has some parameters too which would give you more granular level of control. See here.

JavaScript/jQuery: global variable inexplicably being reset, causing menu contraction issue

http://jsfiddle.net/VhjR7/1/
When you click the my lists menu once, it expands, but if you click it again, it doesn't contract.
The problem is listsExpanded being inexplicably reset to false after it is set properly to true by listsExpand(). This causes the check within $('#mid-wrap').delegate() to inappropriately call listsExpand() again, instead of listsContract() like it should.
I can't figure out where or why this reset is occurring, but I think it has something to do with the sticky light blue menu functionality. Before I started removing and replacing this blue bar after scrolling to fix an IE7 bug, there was no issue with expansion/contraction of the little white menu.
Any ideas on what's causing this?
The issue is that the hover event does not support both function arguments (in and out) when used with .delegate(). You will need to use mouseenter and mouseleave instead of hover.
Change to this:
$('#mid-wrap').delegate('#lists', 'mouseenter', function() {
listsMouseIn = true;
}).delegate('#lists', 'mouseleave', function() {
listsMouseIn = false;
});
FYI, if these HTML objects are static, not added dynamically, you could significantly simplify your code by using direct event handlers on that actual objects rather than .delegate and just stopPropagation() when you've processed the click. Then, you'd see the click first in the object and wouldn't be processing the same click multiple times causing you to need all these global flags to keep track of state.
You could also just use the visibility of the object as your detection mechanism for whether the menu is open/closed too rather than a global variable.
The first part of your hover handler (with listsMouseIn = true;) never actually fires so whenever you click, your $('body').mouseUp() handler assumes that you are not hovering the lists button, and therefore hides the menu just for the $('#mid-wrap').delegate(...) handler to show it again milliseconds later.
Replacing
$('#mid-wrap').delegate('ul#lists', 'hover', funcIn, funcOut);
with
$('#mid-wrap').delegate('ul#lists', 'mouseover', funcIn).
delegate('ul#lists', 'mouseout', funcOut);
seems to do the trick.

Categories

Resources