Change class of active bootstrap button on hover - javascript

If I want to change the class of this bootstrap button on hover with jQuery, so that the styling of the button changes to the new custom class, that I would like to add with "addClass":
<div id="tile-sort" class="btn-group" data-toggle="buttons">
<label id="sort-hello" class="btn btn-primary btn-xs">
<input type="radio" name="sort-option" value="hello">Hello
</label>
</div>
The below code works:
$('#tile-sort').hover(
function() {
$('.btn-primary').addClass('sort-hover-nonactive');
},
function() {
$('.btn-primary').removeClass('sort-hover-nonactive');
}
);
However, if I attempt to change the class of this "active" bootstrap button on hover with jQuery:
<div id="tile-sort" class="btn-group" data-toggle="buttons">
<label id="sort-goodbye" class="btn btn-primary btn-xs active">
<input type="radio" name="sort-option" value="goodbye">Goodbye
</label>
</div>
The below code does not work:
$('#tile-sort').hover(
function() {
$('.btn-primary.active').addClass('sort-hover-active');
},
function() {
$('.btn-primary.active').removeClass('sort-hover-active');
}
);
Can someone point me in the correct direction for this class adding/removing to happen?

Looks like the issue might be coming from somewhere else, maybe you didn't set !important on your custom css?
I've tried it as follows:
.sort-hover-active {
background-color:red !important;
}
Here is a demo
EDITED:
Following the comments of #jshthornton, I edited the code to be more in line with bootstrap's native code. Here is what I did:
$('#tile-sort').hover(
function() {
$('#sort-goodbye').removeClass('btn-primary').addClass('btn-danger');
},
function() {
$('#sort-goodbye').removeClass('btn-danger').addClass('btn-primary');
}
);
This way you're basically making use of existing bootstrap code instead of applying cumbersome workarounds like !important which should preferably be avoided, if possible.
And here is a demo of that

With js:
.btn-primary.active.sort-hover-active {
background-color:red;
}
Using it like this may be overwritten time to time. If this is the case just find the selector path which has the strongest weight.
http://css-tricks.com/specifics-on-css-specificity/
Without js:
.btn-primary.active:hover {
background-color:red;
}
This is the "best" way to do it if you only need visual changes on hover. This is also the least intensive to the DOM due to less mutations. With this method you can remove your JS hover code.
This also has issues in some legacy IEs. Read more here: css: does every class support :hover state?

Try with toggleClass method and hover event, check this example:
$(document).ready(function(){
$("#my-btn").hover(function(){
$(this).toggleClass("btn-danger");
});
});
<!-- libs -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<!-- button -->
<a class='btn btn-primary' id='my-btn'>
class change on hover
</a>
If you want to change the text or reuse this logic
, you can create a plugin check this example(toggleBtn plugin):
// pluglin toogleBtn
jQuery.fn.extend({
toggleBtn: function (normalBtnOps, hoverBtnOps) {
var self = this;
self.attr('class', 'btn ' + normalBtnOps.class);
self.text(normalBtnOps.text);
this.hover(function () {
self
.attr('class', 'btn ' + hoverBtnOps.class)
.text(hoverBtnOps.text);
}, function(){
self
.attr('class', 'btn ' + normalBtnOps.class)
.text(normalBtnOps.text);
});
}
});
// test Plugin
$('#my-btn').toggleBtn(
{'class': 'btn-primary','text' : 'normal btn'},
{'class': 'btn-danger','text' : 'hover btn'}
);
$('#my-btn-2').toggleBtn(
{'class': 'btn-warning','text' : 'warning!'},
{'class': 'btn-dark','text' : 'Dark!'}
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<a id='my-btn' href='#'></a>
<a id='my-btn-2' href='#'></a>
Good Luck!.

Related

How can I show/hide a bootstrap spinner with jQuery?

I'm trying to show a bootstrap spinner after a click on a button and then hide it after getting a response from an API (basically a loading status).
My button is as follow:
<div class="col-6">
<button type="button" name="btn-enviar" class="btn btn-primary w-100">
<span class="spinner-border spinner-border-sm mr-3" id="spinner" role="status" aria-hidden="true">
</span>Enviar</button>
</div>
So far I've tried to comment/uncomment my span tag with no luck, there would be an easier way to start/stop my spinner?
My comment/uncomment functions which I took from here and are not working (as requested):
function comment(element) {
element.html('<!--' + element.html() + '-->')
}
function uncomment(element) {
element.html(element.html().substring(4, element.html().length - 3))
}
Html (with added class .spinner):
<div class="col-6">
<button type="button" name="btn-enviar" class="btn btn-primary w-100">
<span class="spinner spinner-border spinner-border-sm mr-3" id="spinner" role="status" aria-hidden="true">
</span>Enviar</button>
</div>
Add css to css-file:
#spinner { display:none; }
body.busy .spinner { display:block !important; }
Or use visibility:
#spinner { visibility:hidden; }
body.busy .spinner { visibility:visible !important; }
JQuery:
$(document).ready( function()
{
$('#spinner').on('click', function()
{
$('body').addClass('busy');
});
});
When done, do:
$('body').removeClass('busy');
With a class like 'busy' added to the body of the html page, you can also do very nice things like blocking input elements and such without extra js code. Let CSS do all the work for you instead of js. You only have to add some extra CSS rules.
PS: Check your html for errors with html validator. If there are errors in the markup, strange things might happen or it doesn't work.
Have fun.
There are animation and -webkit-animation css attributes on the element.
Use a class like this
.stop {
animation-name: none !important;
-webkit-animation-name: none !important;
}
With JQuery you can toggle this class on the element. If it is added, the animation will stop.
Update
This will show then hide the spinner.
$(() => {
$('button').on('click', e => {
let spinner = $(e.currentTarget).find('span')
spinner.removeClass('d-none')
setTimeout(_ => spinner.addClass('d-none'), 2000)
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://getbootstrap.com/docs/4.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="canonical" href="https://getbootstrap.com/docs/4.3/components/spinners/">
<button class="btn btn-primary" type="button">
<span class="d-none spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
Click me...
</button>
I just faced the same problem and solved it with visibility style attribute.
HTML:
<span class="spinner-border spinner-border-sm" id="spinner" style="visibility: hidden"></span>
JS:
let spinner = document.getElementById("spinner");
spinner.style.visibility = 'visible'; //'hidden'
I didn't get your code exactly but I am putting my idea, you can try if feasible.
$(document).ready(function() {
$("#spinner").spinner({
start: function(event, ui) {
$('#d1').html("Spinner has started ");
},
stop: function(event, ui) {
$('#d1').html("Spinner has stopped ");
}
});
});
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.1/themes/blitzer/jquery-ui.css" rel="stylesheet">
<input id="spinner" class='selector' value=12 size=3>
<div id=d1></div>

detecting class changes in Bootstrap Switch Jquery (converting working checkbox JS to button js)

I am trying to convert a piece of JQuery that changes the class of a tr when checked to a piece of JQuery that changes the class of a tr when a button gets a class called "active". I am a JQuery/Javascript newbie and I am at a loss.
For those who have suggested it's a duplicate, I have tried to detect class and failed (updated code below).
ORIGINAL CODE (THAT WORKS)
javascript:
var $input_class = $('.addCheckbox');
function setClass() {
var tr = $(this).closest( "tr" );
if ($(this).prop('checked') == true){
tr.addClass( "highlight" );
}
else{
tr.removeClass( "highlight" );
}
}
for(var i=0; i<$input_class.length; i++) {
$input_class[i].onclick = setClass;
}
MY HORRIBLE TRY (UPDATED BELOW...NO LONGER THIS)
javascript:
var $input_class = $('.btn-group .btn-toggle .btn');
function setClass() {
var tr = $(this).closest( "tr" );
if ($(this).prop('.btn-success .active')){
tr.addClass( "highlight" );
}
else{
tr.removeClass( "highlight" );
}
}
for(var i=0; i<$input_class.length; i++) {
$input_class[i].onclick = setClass;
}
I am using the Bootstrap Switch Plugin which converts checkboxes to toggles
http://www.bootstrap-switch.org/
The converted html looks like this:
<tr>
<td width="15px"><input class="addCheckbox" type="checkbox" value="true" style="display: none;">
<div class="btn-group btn-toggle" style="white-space: nowrap;">
<button class="btn active btn-success btn-md" style="float: none; display: inline-block; margin-right: 0px;">YES</button>
<button class="btn btn-default btn-md" style="float: none; display: inline-block; margin-left: 0px;"> </button>
</div>
</td>
<td width="85px">May 2016</td><td class="restaurant-name">
Joe's Crab Shack
</td>
<td class="text-center">
#my table info
</td>
</tr>
UPDATE!!! As per 'duplicate' suggestions.
After looking through this question (which was very helpful), I have changed my code to this, and I still can't get it to work. I am wondering if it is having trouble finding the exact input class? Because the plugin converts the checkbox to html, I can't (or don't know how) set specific names or ids for the buttons.
javascript:
var $input_class = $('.btn');
var tr = $(this).closest( "tr" );
function checkForChanges()
{
if ($('.btn').hasClass('btn-success'))
tr.addClass( "highlight" );
else
tr.removeClass( "highlight" );
}
for(var i=0; i<$input_class.length; i++) {
$input_class[i].onclick = checkForChanges;
}
There are issues in your code resulting from not being familiar with the language. Also keep in mind this jQuery what you posted, not javascript.
As I am not quite sure what is your final objective here so let's go step by step.
First of all:
$('.btn-group .btn-toggle .btn');
The above means an element with all three classes class="btn-group btn-toggle btn" and I do not see such in your code. Are you sure you didn't want to use $('.btn-group, .btn-toggle, .btn'); ? At the moment var $input_class is empty, so later in your code you loop through nothing.
Second thing:
as I posted in the comments make sure you run your script after loading jQuery and rest of the content of the page. If your script is above jQuery, like this:
<head>
<script type="text/javascript">/* Your script here */</script>
<script type="text/javascript" src="jquery-1.9.1.min.js"></script>
</head>
Above won't work for two reasons:
You run your script before you load the jQuery, so commands like $(".class") aren't understood.
You run your script before loading the content, so for example var $input_class = $('.addCheckbox'); will be empty, because the element with class addCheckbox doesn't exist yet. [for this one assume jQuery is included before the script, but the script is still inside the <head>].

click event on button prevented for some reason

I'm trying to modify the css properties of a div by triggering a click event. For some reason, this isn't happening and it's driving me crazy. Do you know why this happens?
The event looks like this:
$("#colButton3").on("click", function() {
unCollapse('#CarouselSpace','#CarouselBody');
});
The unCollapse function is this:
var unCollapse = function(headerElement, bodyElement) {
$(headerElement).css('margin-top', '1500px');
$(bodyElement).css('min-height', '820px');
};
And the button itself is generated with jquery, but its html is:
<button class="btn btn-success" href="#" id="colButton3" style="display: inline-block;">Learn More</button>
The target divs are these:
<div id="CarouselSpace" class="row"><h1 id="CarouselHeader"></h1></div>
<div id="CarouselBody" class="row"></div>
What am I doing wrong?
Thank you guys.
Dynamic elements needs to have the bind on the document not the element itself as the element is loaded after the document loads
$(document).ready(function() {
$(document).on("click", "#colButton3", function() {
unCollapse('#CarouselSpace', '#CarouselBody');
});
});
var unCollapse = function(headerElement, bodyElement) {
$(headerElement).css('margin-top', '1500px');
$(bodyElement).css('min-height', '820px');
};
#CarouselBody,
#CarouselSpace {
border: 1px solid #ff6600;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="CarouselSpace" class="row">
<h1 id="CarouselHeader">Header</h1>
</div>
<div id="CarouselBody" class="row">Body</div>
<button id=colButton3>button
</button>
The code should work, you are probably trying to bind click event before you create the button. Try using $.live or bind after creating the button.

Show div hidden by "display: none" using JS?

The below HTML and JavaScript is working as expected, but I want to make sure I am using this correctly.
I have two divs but only one needs to be displayed depending on the value of mode.
HTML:
<body>
<div id="a-div" style="display: none;">
<button id="add" class="btnstyle">Add </button>
</div>
<div id="d-div" style="display: none;">
<button id="delete" class="btnstyle">Delete</button>
</div>
</body>
JS:
//$("#a-div").hide();
//$("#d-div").hide();
var mode = 'add';
//var mode = 'delete';
if (mode === 'add') {
$("#a-div").show();
} else {
$("#d-div").show();
}
This is giving me expected results. Is there a better way of reversing the style="display: none" attribute?
Your current code should be working fine, but there are many ways of solving this problem. I would recommend using jQuerys toggle():
$("#a-div").toggle(mode === "add");
$("#a-div").toggle(mode === "delete");
Alternatively, you could give them the id´s add-div and delete-div and make one of them visible like this:
$("#" + mode + "-div").show();
You can use:
$("#a-div").toggle();
Alternatively;
.show() / .hide()
.fadeIn() / fadeOut()
There's several methods to do this (like you can see in other answers) but i think the show() function is enough and do the work in your case.
You can also use css() method of JQuery like following :
$("#a-div").css('display','block');
Hope this helps.
You need to modify the display property of the inline style attribute.
Like this...
var mode = 'add';
if (mode === 'add') {
$("#a-div")[0].style.display = 'block';
} else {
$("#d-div")[0].style.display = 'block';
}
Or you can use something like inherit instead of block.
Another option is to move the styles to css:
html:
<div id="a-div" class="notdisplayed">
<button id="add" class="btnstyle">Add </button>
</div>
<div id="d-div" class="notdisplayed">
<button id="delete" class="btnstyle">Delete</button>
</div>
css:
.notDisplayed {display:none;}
Script:
$("#a-div").addClass("notDisplayed");
$("#d-div").removeClass("notDisplayed");
This method is more general than show/hide, as it can be extended to any style rule.

How to change Bootstrap style before it is shown?

I've been trying to manipulate the bootstrap tooltip's positioning without success.
Attempt #1:
stuff.tooltip({
container: 'body',
placement: function(tip, el) {
// played with tip, but it still add style: top, left at the end...
}
});
Attempt #2:
stuff.tooltip({
container: 'body',
placement: 'top'
}).on("show.bs.tooltip", function() {
// don't have access of the tip here
});
Attempt #3:
stuff.tooltip({
container: 'body',
placement: 'top'
}).on("shown.bs.tooltip", function() {
// doing anything to the tip at this point would cause visible change
});
Any ideas?
Handling with CSS
The best case scenario is you can style tooltips exclusively with CSS that is written ahead of time. As long as you don't need to dynamically change the style of the tooltip based on information only available at runtime. The CSS will immediately apply to elements inserted into the DOM without the FOUC problem.
$(function () {
$('[data-toggle="tooltip"]').tooltip({
container: 'body',
placement: 'bottom'
});
});
.tooltip .tooltip-inner {
background-color: yellow;
color: black;
}
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.js"></script>
<button type="button" class="btn btn-default"
title="Tooltip on bottom" data-toggle="tooltip" >
Tooltip on Bottom
</button>
What specifically are you trying to do where the default placement options and CSS don't apply?
Handling on Show
You can't access the tooltip during the show event... however... you can dynamically change the template option so the resulting tooltip will have custom styles.
$(function () {
$('[data-toggle="tooltip"]').tooltip({
container: 'body',
placement: 'bottom'
}).on("show.bs.tooltip", function (e) {
var $tooltip = $(this).data('bs.tooltip')
var $template = $($tooltip.options.template)
// whatever modifications you'd like to do here while invisible
$template.find('.tooltip-inner')
.css("background", "yellow")
.css("color", "black")
// reapply template
$tooltip.options.template = $template[0].outerHTML;
});
});
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.js"></script>
<button type="button" class="btn btn-default"
title="Tooltip on bottom" data-toggle="tooltip" >
Tooltip on Bottom
</button>
Handling On Shown
You could modify the tooltip template to include a hidden class, and style that with visibility: hidden;. Then, once the tooltip has appeared in the shown event, modify it however you want and finish by removing the class.
Note: do not try to use the class name hidden or hide as these are taken by bootstrap and set display:none. If the tooltip display is set to none, then the element will be incorrectly positioned. So we have to let it occupy space, but just stay invisible until we're ready to render.
$(function () {
$('[data-toggle="tooltip"]').tooltip({
container: 'body',
placement: 'bottom',
template: '<div class="tooltip init" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
}).on("shown.bs.tooltip", function (e) {
var $tooltip = $(this).data('bs.tooltip')
// whatever modifications you'd like to do here while invisible
$tooltip.$tip.find('.tooltip-inner')
.css("background", "yellow")
.css("color", "black")
// remove invisibility cloak
$tooltip.$tip.removeClass('init');
});
});
.tooltip.init {
visibility: hidden;
}
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.js"></script>
<button type="button" class="btn btn-default"
title="Tooltip on bottom" data-toggle="tooltip" >
Tooltip on bottom
</button>

Categories