Bootstrap 5 update Tooltip Title with Javascript - javascript

In Bootstrap 4 I used the following sample code to update the title of the tooltip (where 'statusIcon' is the element, in this case is a font awesome icon, but same principal would apply for a button or anything else:
$(statusIcon).attr('data-original-title', 'Check Error logs for details').tooltip();
Razor page html element:
<i class="fas fa-circle fa-lg" id="statusIcon:#item.Id" data-bs-toggle="tooltip" data-bs-placement="right" title="Started" data-bs-animation="false" style="font-size: 1.5em; color: #28A745"></i>
Reading the manual for Bootrap 5, they don't appear to tell us how to achieve this with Vanilla JS
What I've tried so far in Javascript:
var statusIconId = 'statusIcon:' + pluginId + '';
var statusIcon = document.getElementById(statusIconId);
document.getElementById(statusIconId).setAttribute("data-bs-original-title", 'Check Error logs for details');
Am using variables in the element Id because I'm working with element in a Razor List View.

You can update the tooltip title by changing the data-bs-original-title attribute
$(function () {
// Init
$('[data-toggle="tooltip"]').tooltip()
// Update jquery
// $('#tt').attr('data-bs-original-title', 'New Tooltip Title');
// Update js
document.getElementById('tt').setAttribute('data-bs-original-title', 'New Tooltip Title');
})
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta1/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button" id='tt' class="btn btn-secondary" data-toggle="tooltip" data-placement="bottom" title="Tooltip title">
Tooltip
</button>

Since Bootstrap 5.0 no longer requires jQuery, use document.querySelector(), then reinitialize the tooltip after modifying the element:
// initialize
const tooltipElement = document.querySelector('[data-bs-toggle="tooltip"]')
let bsTooltip = new bootstrap.Tooltip(tooltipElement)
// update
tooltipElement.title = 'New Title'
bsTooltip = new bootstrap.Tooltip(tooltipElement)
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css" integrity="sha512-HK5fgLBL+xu6dm/Ii3z4xhlSUyZgTT9tuc/hSrtw6uzJOvgRr2a9jyxxT1ely+B+xFAmJKVSTbpM/CuL7qxO8w==" crossorigin="anonymous" />
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta1/dist/js/bootstrap.bundle.min.js"></script>
<i class="fas fa-circle fa-lg" id="statusIcon:#item.Id" data-bs-toggle="tooltip" data-bs-placement="right" title="Started" data-bs-animation="false" style="font-size: 1.5em; color: #28A745"></i>
(updated to use your Razor page element)

Here is example if your tooltip is in loop, and you want to update the clicked button tooltip.
Use case:
Copy button in table row using clipboard.js
Code:
index.blade.php
<button type="button" data-bs-toggle="tooltip" data-bs-placement="top" title="Copy to clipboard" class="btn-clip btn btn-primary" data-clipboard-text="{{ user.domain }}">Copy</button>
index.js
let clipboard = new ClipboardJS('.btn-clip');
clipboard.on('success', function (e) {
let trigger_button = e.trigger;
// update the tooltip title, get the tooltip instance, and show it
trigger_button.setAttribute('data-bs-original-title', 'Copied!');
let btn_tooltip = bootstrap.Tooltip.getInstance(trigger_button);
btn_tooltip.show();
// reset the tooltip title
trigger_button.setAttribute('data-bs-original-title', 'Copy to clipboard');
});

I had to do the following to get it working with Bootstrap 5 and ClipboardJS 2:
<script src="js/clipboard.js"></script>
<script src="js/jquery-3.6.0.js"></script>
<script src="js/bootstrap.bundle.js"></script>
<script>
$(document).ready(function () {
// Tooltip
$('[data-bs-toggle="tooltip"]').tooltip()
// Clipboard
const clipboard = new ClipboardJS('.btn-clipboard')
clipboard.on('success', function(e) {
$('.tooltip-inner').html('Copied!')
$(e.trigger).tooltip('update')
e.clearSelection()
})
clipboard.on('error', function (e) {
var fallbackMsg = /Mac/i.test(navigator.userAgent) ? 'Press \u2318 to copy' : 'Press Ctrl-C to copy'
$('.tooltip-inner').html(fallbackMsg)
$(e.trigger).tooltip('update')
})
})
</script>
<button type="button" class="btn btn-clipboard" data-clipboard-text="copied text" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Click/touch to copy">Button</button>

only thing worked for me was disposing tooltip and rebuilding it again with setTimeout and 'enable' instead of 'show' for repeat hover..
$('#shareLink').on('click', function (e) {
$('#shareLink').tooltip('dispose').attr('title', 'Link copied!');
$('#shareLink').tooltip('show');
setTimeout( function () {
$('#shareLink').tooltip('dispose').attr('title', 'Copy link to Clipboard');
$('#shareLink').tooltip('enable');
}, 2000);
});

For bootstrap 5.2, use this:
const tooltipInstance = bootstrap.Tooltip.getInstance(tooltipElement);
tooltipInstance.setContent({ '.tooltip-inner': 'new title'});
where tooltipElement is either a html element or a string which represents the query selector. E.g. : '.tooltip'

Related

fontawesome onclick icon change angular using material table

I want to fill favorite icon when it's empty. While click on the favorite icon i have to display solid favorite icon.
I tried like below code
<span class="icon iconVisibile" (click)="isClicked()">
<i class="fa-star"[ngClass]="isSelectedFav ? 'fas' : 'far'"></i>
</span>
ts
public isSelected:boolean = false;
isClicked(){
this.isSelected = true;
console.log(this.isSelected);
}
with above code that is not working please let me know what I am doing wrong here
Demo Your problem seems that font awesome return i element tag to svg. That is why you can't change it. you should close autoReplaceSvg property in font awesome
put below ones in index.html
<script type="text/javascript">
window.FontAwesomeConfig = { autoReplaceSvg: false }
</script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/js/all.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css" rel="stylesheet" />
component.ts
public isSelected:boolean = false;
isClicked(){
this.isSelected = true;
}
html
<span class="icon iconVisibile" (click)="isClicked()">
<i class="fa-star"[ngClass]="isSelected ? 'fas' : 'far'"></i>
</span>

Close jquery modal

I'm importing Jquery Modal from these two links (js and css)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.css" />
I've added the following html code inside the body
<button onclick="load();" class="btn btn-primary">
<span class="fa fa-icon fa-filter"></span>
Filtrar
</button>
<div id="loadingModal" class="" style="display:none">
Cargando
</div>
and the following is in a js file
function load() {
openLoadingModal();
doSomething();
closeModal();
}
function openLoadingModal(e) {
$("#loadingModal").modal("show");
var count = 0;
var points = "";
var intervalId = window.setInterval(function(){
count++;
$("#loadingModal").text("Cargando" + ".".repeat(count % 3 + 1));
}, 1000);
return intervalId;
}
With this, the modal opens as I expect. The thing is that I want to close the modal when this ends. But the solutions I've found didn't work. I tried the following:
$("#loadingModal").modal("close");
$("#loadingModal").modal().close();
$("#loadingModal").modal().close;
$("#loadingModal").modal("toggle");
$("#loadingModal").modal().toggle();
None of this closes the modal as it should (maybe hides the modal, but not all of it, since there is a black screen)
I think this shouldn't be this hard, but every link I get in tells me to do one of this
Thanks
If there is only one modal on the page, use this:
$.modal.close();

Add icon to HTML button when clicked

Here's my button:
<button type="button" id="myButton" class="myButtonCSS" onclick="handleMyButtonClick()"> myButton! </button>
In my handleMyButtonClick() function I have a bit of logic, but what I want to accomplish is to add a waiting icon while it's doing that logic. I found out how to do this with this code:
<i class="fa fa-spinner fa-spin"></i>
If I add that to my original button statement it works, but it's ALWAYS there. I only want this to show up when clicked. I'm trying to add the "i class" to the button within my JavaScript on click function. I've tried to use .classList.add() but I must be doing it wrong, or approaching it wrong entirely. How can I do this?
What you need to do is update the inner html of button in the beginning of your method handleMyButtonClick()
var btn = document.getElementById('myButton');
btn.innerHTML = '<i class = "fa fa-spinner fa-spin"></i> Please wait...';
Then when you are done with your logic, reset the button back to the original state.
btn.innerHTML = 'myButton!';
Have a look at this complete code. Works just as you wanted.
function handleMyButtonClick(){
// Get button element
btn = document.getElementById('myButton');
// Set the spinner
btn.innerHTML = '<i class = "fa fa-spinner fa-spin"></i> Please wait...';
// Do the work. A sample method to wait for 3 second.
setTimeout(function(){
console.log("work done");
// When the work is done, reset the button to original state
btn.innerHTML = 'myButton!';
}, 3000);
}
<button type="button" id="myButton" class="myButtonCSS" onclick="handleMyButtonClick()"> myButton! </button>
I guess this will work out for you please check
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<button type="button" id="myButton" class="" onclick="handleMyButtonClick()"> <span id='spin'></span>myButton! </button>
</body>
<script>
function handleMyButtonClick(){
$("#spin").addClass("fa fa-spinner fa-spin");
setTimeout(()=>{
//Do some logic
$("#spin").removeClass("fa fa-spinner fa-spin");
},5000)
}
</script>
</html>
As javascript uses single thread, and if your code is synchronous, you will not be able to see the style change immediately. Once the execution of the method is finished, then it will renders the UI with new style. So, in your case, it wont' show any difference. As you are showing and hiding by the end of the function. If you want show the spinner you have to hide the spinner in setTimeout().
Try following:
<button type="button" id="myButton" class="myButtonCSS" onclick="handleMyButtonClick()">
<i class="fa fa-spinner fa-spin"></i>
myButton!
</button>
function handleMyButtonClick() {
document.getElementById('myButton').classList.add('loading');
// your logic goes here
setTimeout(function() {
document.getElementById('myButton').classList.remove('loading');
}, 2000);
}
.myButtonCSS {
position: relative;
}
.myButtonCSS .fa-spinner {
display: none;
position: absolute;
left: 5px;
top: 5px;// you can modify according to your button height and width
}
.myButtonCSS.loading .fa-spinner {
display: inline-block;
}
Thank you for all of your suggestions but I have a far simpler answer.
tempButton = document.getElementById('myButton'); //snag button
tempButton.innerHTML = '<i class = "fa fa-spinner fa-spin"></i> Please wait...';
I'm VERY new to web programming. Sorry I cannot explain for you, but this 1 line change the code of my button within my JavaScript on click function instantly.

Change class of active bootstrap button on hover

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!.

Multirow selection(getRangeAt) and surroundContents() for text editor

Im trying to create a simple text editor for a web site.
I want to add to him something like the code button in this site.
So by selecting a specific text, color it's background with gray color.
Here is what i have for now but if i have a multi row text selected(rows created by pressing enter) the function test() doesn't work. It works only if i select a row each time.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="Awesome/css/font-awesome.css">
</head>
<body onload="InitEditable()">
<div style="margin-left:10px;">
<p>
<div class="btn-group">
<a class="btn" href="#" onclick="fontEdit('bold')"><i class="icon-bold"></i></a>
<a class="btn" href="#" onclick="fontEdit('italic')"><i class="icon-italic"></i></a>
<a class="btn" href="#" onclick="fontEdit('underline')"><i class="icon-underline"></i></a>
<a class="btn" href="#" onclick="test()"><i class="icon-link"></i></a>
<a class="btn" href="#" onclick="fontEdit('justifyLeft')"><i class="icon-align-left"></i></a>
<a class="btn" href="#" onclick="fontEdit('justifyCenter')"><i class="icon-align-center"></i></a>
<a class="btn" href="#" onclick="fontEdit('justifyRight')"><i class="icon-align-right"></i></a>
<a class="btn" href="#" onclick="fontEdit('justifyFull')"><i class="icon-align-justify"></i></a>
</div>
</p>
</div>
<div style="margin-left:10px;"><iframe id="textEditor" style="width:500px;height:170px;font-family:arial;font-size:11px;"></iframe></div>
<script type="text/javascript">
var editorDoc;
var editor;
function InitEditable()
{
editor = document.getElementById("textEditor");
editorDoc = editor.contentwindow.document;
var editorBody = editorDoc.body;
if ('contentEditable' in editorBody) {
// allow contentEditable
editorBody.contentEditable = true;
}else { // Firefox earlier than version 3
if ('designMode' in editorDoc) {
// turn on designMode
editorDoc.designMode = "on";
}
}
}
function fontEdit(x,y)
{
editorDoc.execCommand(x,"",y);
editorDoc.focus();
}
function test(){
var range = document.getElementById("textEditor").contentwindow.window.getSelection().getRangeAt(0);
var newNode = document.createElement('div');
newNode.style.backgroundColor = "gray";
range.surroundContents(newNode);
return false;
}
</script>
</body>
</html>
There must be a problem with surroundContents() and divs but cannot think something to solve it.
Any idea is welcomed!
Thanks in advance.
One option is the class applier module of my Rangy library (demo)
Live demo: http://jsfiddle.net/D7s5j/
CSS:
.code {
background-color: #ccc;
font-family: Courier New, monospace;
}
JS:
var codeApplier = rangy.createCssClassApplier("code");
codeApplier.applyToSelection();
So the problem is that the contenteditable object, creates <div> so this couldn't let surroundContents() work properly and add it's own <div>s around the selected range.
I solve my problem finally by adding this code
$("#textEditor>div").replaceWith(function() { return $(this).contents(); });
which deletes <div>s tags from the contenteditable object.
Also you can add this for create a <br> tag after enter pressed.
$("#textEditor > div").before("<br />").contents().unwrap();
For the second code thank VisioN.

Categories