I am trying to get a button in the bootstrap popover to change class when I hover over it using jQuery but for some reason, it is not working. I have looked everywhere and I am using the same method as everybody else for hover events in jQuery but, for some reason, it is just not working.
I am trying to change the classes from btn btn-default to btn btn-success on hover. I realize that this could be achieved using CSS(the color change) but this is supposed to work and it is not working and I wanna know why and resolve it.
I am using : Bootstrap 3.3.6, jQuery
The Entire HTML file :
<!DOCTYPE html>
<html>
<head>
<title>Easy ToDo</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<!--<script type="text/javascript" src="https://cdn.jsdelivr.net/bootstrap.native/1.0.2/bootstrap-native.min.js"></script> -->
<script>
function checkTaskStatus(checkbox) {
var tasktext = document.getElementById('tasktext');
var taskrow = document.getElementById('taskrow');
if (checkbox.checked){
taskrow.className = "active";
tasktext.className = "text-muted";
tasktext.style.textDecoration = "line-through";
}
else {
document.getElementById("taskrow").className = "warning";
document.getElementById('tasktext').className = "text-success";
tasktext.style.textDecoration = "none";
}
}
function changeBtn(button) {
var temp = button.className;
if(temp === "btn btn-primary") {
button.className = "btn btn-danger";
button.innerText = "Close";
}
else {
button.className = "btn btn-primary";
button.innerText = "Add New Task";
}
}
</script>
<script>
$(document).ready(function(){
$('[data-toggle="popover"]').popover({
html: true,
title: 'New Task',
trigger: 'click',
content: function () {
return $('.popoverContent').html();
},
placement: 'right'
});
});
</script>
<script>
$(document).ready(function () {
$("#btntask").hover(function () {
$(this).removeClass('btn btn-default');
$(this).addClass('btn btn-success');
}, function () {
$(this).removeClass('btn btn-success');
$(this).addClass('btn btn-default');
});
});
</script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<h1 style="border: 2px solid rebeccapurple; margin-top: 0; background-color: rebeccapurple; color: white; padding-left: 0.6em; padding-bottom: 0.1em; margin-bottom: 1.5em;">An Easy To - Do Web App!</h1>
<button type="button" class="btn btn-primary" style="margin-bottom: 15px; margin-left: 10px;" data-toggle="popover" onclick="changeBtn(this)">Add New Task</button>
<div class="popoverContent hide">
<label for="newTask">Task:</label>
<textarea rows="3" name="newTask" class="form-control input-lg" placeholder="Task HTML"></textarea>
<button class="btn btn-default" type="submit" style="margin-top: 10px;" id="btntask">Done</button>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th style="width: auto"> </th>
<th style="width: auto">#</th>
<th style="width: auto">Date</th>
<th style="width: auto">Task</th>
<th style="width: auto">Notes</th>
</tr>
</thead>
<tbody>
<tr class="warning" id="taskrow">
<td><div class="checkbox"><label><input type="checkbox" onclick="checkTaskStatus(this)"></label></div></td>
<td scope="row" style="font-weight: bold;">1</td>
<td><p style="font-style: italic; font-weight: bold;">7th May, 2016</p></td>
<td class="text-success" id="tasktext" style="text-decoration: none;"><h5 id="task-heading" style="margin-top: 0; text-decoration: underline; font-weight: bold;">Tesla Share Purchase Reasearch:</h5>
<ul>
<li>Find out how an Australian citizen can purchase shares in an American company (e.g. Tesla) which is not listed on the ASX (Australian Stock Exchange)</li>
<li>Prepare a brief list of the steps, costs and general time frame for an Australian to get set up to purchase share in American companies</li>
<li>Please also state the current stock price of Apple, Google (potentially Alphabet as they are the parent??), Facebook, Twitter and Tesla</li>
<li>Bullet points are fine</li>
<li>Please include any relevant links</li>
<li>Spend no longer than 1.5 – 2 hours on this</li>
</ul>
</td>
<td><div class="form-group">
<textarea class="form-control input-md" rows="4" placeholder="Notes"></textarea>
<button class="btn btn-default btn-block" type="submit" style="margin-top: 10px;">Save</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
Note that, I am fairly new to jQuery and JS so if there is any inaccuracies on my part, please point them out.
The issue is when you are trying to add the hover state on the popover , the popover element is not yet available. The element is only added when you click. Hence, the function in $(document).ready() actually adds no hover state.
Instead use jQuery .on
If your hover has not much work to do, you can opt for css hover
#element:hover
{
/*Add your css after hover here*/
}
As pointed out by #Sukhmeet Singh the popover did not appear until on click and not on document.ready.
So I tweaked my script from :
$(document).ready(function () {
$("#btntask").hover(function () {
$(this).removeClass('btn btn-default');
$(this).addClass('btn btn-success');
}, function () {
$(this).removeClass('btn btn-success');
$(this).addClass('btn btn-default');
});
});
To :
$(document).ready(function () {
$('[data-toggle="popover"]').on('click', function () {
$("#btntask").hover(function () {
$(this).removeClass('btn btn-default');
$(this).addClass('btn btn-success');
}, function () {
$(this).removeClass('btn btn-success');
$(this).addClass('btn btn-default');
});
});
});
And it worked. The popover is non-existent in document.ready but appears there when I click on the button with the property [data-toggle="popover"] and thus, when I target the button I want to highlight then, it does it.
Related
Im just trying to build a basic site for linking tenants and properties, and I am coming into some issues with a collapsible web grid. This javascript comes from a tutorial, have repurposed it to fit my task. The issue is my javascript simply doesnt seem to be running. Find below my cshtml and also my shared layout.
Cshtml
#model IEnumerable<HousingProject.Models.Property>
#{
ViewBag.Title = "Index";
WebGrid grid = new WebGrid(source: Model, canSort: false);
}
<style type="text/css">
th, td {
padding: 5px;
}
th {
background-color: rgb(248, 248, 248);
}
#gridT, #gridT tr {
border: 1px solid #0D857B;
}
#subT, #subT tr {
border: 1px solid #f3f3f3;
}
#subT {
margin: 0px 0px 0px 10px;
padding: 5px;
width: 95%;
}
#subT th {
font-size: 12px;
}
.hoverEff {
cursor: pointer;
}
.hoverEff:hover {
background-color: rgb(248, 242, 242);
}
.expand {
background-image: url(/Content/themes/base/images/pm.png);
background-position: -22px;
background-repeat: no-repeat;
}
.collapse {
background-image: url(/Content/themes/base/images/pm.png);
background-position: -2px;
background-repeat: no-repeat;
}
</style>
<h2>Index</h2>
<p>
#using (Html.BeginForm("Index", "Property", FormMethod.Get))
{
#Html.TextBox("filter")
<input type="submit" value="Search" />
}
</p>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.HouseNumber)
</th>
<th>
#Html.DisplayNameFor(model => model.StreetName)
</th>
<th>
#Html.DisplayNameFor(model => model.Town)
</th>
<th>
#Html.DisplayNameFor(model => model.City)
</th>
<th>
#Html.DisplayNameFor(model => model.Postcode)
</th>
<th>
#Html.DisplayNameFor(model => model.MaxOccupancy)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.HouseNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.StreetName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Town)
</td>
<td>
#Html.DisplayFor(modelItem => item.City)
</td>
<td>
#Html.DisplayFor(modelItem => item.Postcode)
</td>
<td>
#Html.DisplayFor(modelItem => item.MaxOccupancy)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Details", "Details", new { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
<div id="main" style="padding:25px; background-color:white;">
#grid.GetHtml(
htmlAttributes: new { id = "gridT", width = "700px" },
columns: grid.Columns(
grid.Column("HouseNumber", "House Number"),
grid.Column("StreetName","Street Name"),
grid.Column("Town", "Town"),
grid.Column("City", "City"),
grid.Column("Postcode", "Postcode"),
grid.Column("MaxOccupancy", "Max Occupancy"),
grid.Column("CurrentOccupancy", "Current Occupancy"),
grid.Column(format: (item) =>
{
WebGrid subGrid = new WebGrid(source: item.CurrentTenants);
return subGrid.GetHtml(
htmlAttributes: new { id = "subT" },
columns: subGrid.Columns(
subGrid.Column("FirstName", "First Name"),
subGrid.Column("Surname", "Surname"),
subGrid.Column("Age", "Age"),
subGrid.Column("Employer", "Employer")
)
);
})
)
)
</div>
<script type="text/javascript">
$(document).ready(function () {
var size = $("#main #gridT > thead > tr >th").size(); // get total column
$("#main #gridT > thead > tr >th").last().remove(); // remove last column
$("#main #gridT > thead > tr").prepend("<th></th>"); // add one column at first for collapsible column
$("#main #gridT > tbody > tr").each(function (i, el) {
$(this).prepend(
$("<td></td>")
.addClass("expand")
.addClass("hoverEff")
.attr('title', "click for show/hide")
//.attr('onclick', 'toggleWebGrid()')
);
//Now get sub table from last column and add this to the next new added row
var table = $("table", this).parent().html();
//add new row with this subtable
$(this).after("<tr><td></td><td style='padding:5px; margin:0px;' colspan='" + (size - 1) + "'>" + table + "</td></tr>");
$("table", this).parent().remove();
});
//by default make all subgrid in collapse mode
$("#main #gridT > tbody > tr td.expand").each(function (i, el) {
$(this).toggleClass("expand collapse");
$(this).parent().closest("tr").next().slideToggle(100);
});
});
//toggle expand and collapse
$(function () {
$("#main #gridT > tbody > tr td.collapse").on('click', function () {
alert('test');
$(this).toggleClass("expand collapse");
$(this).parent().closest("tr").next().slideToggle(100);
});
});
</script>
Shared Layout
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Application name", "Index", "Home", null, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>#Html.ActionLink("Contact", "Contact", "Home")</li>
<li>#Html.ActionLink("Properties","Index","Property")</li>
</ul>
#Html.Partial("_LoginPartial")
</div>
</div>
</div>
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© #DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
</body>
</html>
Im sure you guys will figure it out, been banging my head for a while now, cant even get the debugger to step into it so I'm sure its something wrong in config not the javascript. Please note the tabled part of the page is simply a legacy thing, I dont desperately want to remove it untill this new webgrid works. Ta.
I simply needed to move the
#Scripts.Render("~/bundles/jquery")
#RenderSection("scripts", required: false)
to head section of the sharedLayout. No idea why MVC defaults them to being at the bottom. Seems unhelpful.
I have a script which has three buttons which shows a div when clicked, now my question is how do I hide those div's so let's say div 1 is opened and I click to open div 2, then make it show div 2 but hide div 1 so that I can have the div's be in the same position, but they only show if they are supposed to.
My script:
<!-- SUPPORT CONTACT FORM START-->
<div class="contactSupportButton"><input type="button" src=".png" alt="contact support button" style="height: 40px; width: 120px" onClick="showSupForm()"/>
<div id="contactSupportForm">
TEST
</div>
</div>
<script type="text/javascript">
function showSupForm() {
document.getElementById('contactSupportForm').style.display = "block";
}
</script>
<!-- SUPPORT CONTACT FORM ENDING-->
<!-- BUSINESS CONTACT FORM START-->
<div class="contactBusinessButton"><input type="button" src=".png" alt="contact business button" style="height: 40px; width: 120px" onClick="showBusForm()"/>
<div id="contactBusinessForm">
TEST
</div>
</div>
<script type="text/javascript">
function showBusForm() {
document.getElementById('contactBusinessForm').style.display = "block";
}
</script>
<!-- BUSINESS CONTACT FORM ENDING-->
<!-- OTHER CONTACT FORM START-->
<div class="contactOtherButton"><input type="button" src=".png" alt="contact other button" style="height: 40px; width: 120px" onClick="showOtherForm()"/>
<div id="contactOtherForm">
TEST
</div>
</div>
<script type="text/javascript">
function showOtherForm() {
document.getElementById('contactOtherForm').style.display = "block";
}
</script>
<!-- OTHER CONTACT FORM ENDING-->
css part:
#contactSupportForm{
display: none;
}
#contactBusinessForm{
display: none;
}
#contactOtherForm{
display: none;
}
Here is a JSFiddle to show the whole process of how it works.
http://jsfiddle.net/m0jdv6u0/3/
You could try this:
function showOtherForm(idElement) {
document.getElementById('contactOtherForm').style.display = "none";
document.getElementById('contactSupportForm').style.display = "none";
document.getElementById('contactBusinessForm').style.display = "none"
document.getElementById(idElement).style.display = "block"
}
And you call in each button passing the id of the div, like this:
showOtherForm('contactOtherForm')
Of course, you can make some verifications, so you don't need to set the display on the 3 divs, but I think you dont need that...
Hope it helped!
There's probably a more elegant way to use classes as selectors and achieve the same functional goal, but here's a solution that would enable you to add additional form / button elements without having to add additional show/hide blocks:
[Note - this is not significantly different from #Cleversou's answer]
function showForm(elemId){
var arr = ["Other", "Business", "Support"] ;
for(var i = 0; i < arr.length; i++){
if(elemId === "contact" + arr[i] + "Form"){
document.getElementById(elemId).style.display = "block";
} else {
document.getElementById("contact" + arr[i] + "Form").style.display = "none";
}
}
}
#contactSupportForm{
display: none;
}
#contactBusinessForm{
display: none;
}
#contactOtherForm{
display: none;
}
<!-- SUPPORT CONTACT FORM START-->
<div class="contactSupportButton"><input type="button" src=".png" alt="contact support button" style="height: 40px; width: 120px" onClick="showForm('contactSupportForm')"/>
<div id="contactSupportForm">
TEST
</div>
</div>
<script type="text/javascript">
</script>
<!-- SUPPORT CONTACT FORM ENDING-->
<!-- BUSINESS CONTACT FORM START-->
<div class="contactBusinessButton"><input type="button" src=".png" alt="contact business button" style="height: 40px; width: 120px" onClick="showForm('contactBusinessForm')"/>
<div id="contactBusinessForm">
TEST
</div>
</div>
<script type="text/javascript">
</script>
<!-- BUSINESS CONTACT FORM ENDING-->
<!-- OTHER CONTACT FORM START-->
<div class="contactOtherButton"><input type="button" src=".png" alt="contact other button" style="height: 40px; width: 120px" onClick="showForm('contactOtherForm')"/>
<div id="contactOtherForm">
TEST
</div>
</div>
<script type="text/javascript">
</script>
<!-- OTHER CONTACT FORM ENDING-->
I have a list of things with links to click for more information which use anchor tags to move down the page. Since there is quite a bit of additional information I have it hidden in expandable/collapsable sections.
So far all I've managed to come up with is an expand collapse on the section itself. I know basically nothing about Javascript so what I have include is some stuff I pieced together from some other sites and research.
I would like for the 'click more' anchor tag link to expand the section automatically when clicked, but something that also collapses it similar to what I have now.
Here is the js I managed to pull together
<script type="text/javascript">
function toggle_visibility(tbid,lnkid) {
if (document.all) {
document.getElementById(tbid). style.display = document.getElementById(tbid).style.display == "block" ? "none" : "block";
}
else {
document.getElementById(tbid).style.display = document.getElementById(tbid).style.display == "table" ? "none" : "table";
}
document.getElementById(lnkid).value = document.getElementById(lnkid).value == "[-] Collapse" ? "[+] Expand" : "[-] Collapse";
}
</script>
<style type="text/css">
.hangingIndent {
text-indent: -24px;
padding-left: 24px;
}
#tbl1 {display:none;}
#lnk1 {
border:none;
background:none;
width:85px;
}
</style>
And here is an example of the body
<body style="background-color: #FFFFFF; margin: 20;">
<p style="font-family: Calibri, sans-serif; font-size: 12pt; padding:0px 20px;" class="hangingIndent">
<input type="checkbox">
<strong>Item one</strong><br />
<em>For more information about Item one click here!</em>
</p>
<br />
<table width="800px" border="0" align="center" cellpadding="4" cellspacing="0">
<tr height="1">
<td bgcolor="#333333" colspan="3"></td>
</tr>
<tr bgcolor="#EEEEEE" height="15">
<td>
<strong><a id="Item1">Item one</a></strong>
</td>
<td bgcolor="#EEEEEE" align="right">
<input id="lnk1" type="button" value="[+] Expand" onclick="toggle_visibility('tbl1','lnk1');">
</td>
</tr>
<tr>
<td colspan="3">
<table width="100%" border="0" cellpadding="4" cellspacing="0" id="tbl1">
<tr>
<td colspan="3">
<p style="font-family: Calibri, sans-serif; font-size: 12pt; padding:0px 20px;">Lots of extra information about Item one</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
<br />
</body>
Thanks for your help!
jquery may be your best route, and in particular the slideToggle or show and hide functions.
In addition, have a peek at jQuery ui accordion
A jquery accordion may be your best route
to hide elements:
document.getElementById(idOfElement).style.display="none"
to show them:
document.getElementById(idOfElement).style.display="block"
lets make a function
function toggleElementDisplay(elementID){
element = document.getElementById(elementID);
if(element.getPropertyValue("display") == "block"){
element.style.display="none";
} else {
element.style.display="block";
}
}
To use it do it like this
<body>
<div id="click" onClick="toggleElementDisplay('stuff');">Toggle</div>
<div id="stuff">Hello</div>
<script>
function toggleElementDisplay(elementID) {
var element = document.getElementById(elementID),
style = window.getComputedStyle(element),
display = style.getPropertyValue("display");
if (display == "block") {
element.style.display = "none";
} else {
element.style.display = "block";
}
}
</script>
</body>
Here is a demo to help
to save space, I would like to consolidate the username and logut buttons at the top of web template into one link. The username would be visible and when you hover over it as in stack overflow or click as in gmail or fb, you have option to logout or do other account related things. Ideally, would like to do this in css or javascript without jquery overhead.
Can anyone recommend simple javascript or other technique as I am very inexperienced in javascript. Don't need complicated full blown drop down menu. It should be something like below, but below is unpredictable...shows menu when page loads etc. Thx.
<html>
<head>
<script>
showMenu = function() {
var div = document.getElementById('box1');
div.style.display = 'block';
}
hideMenu = function() {
var div = document.getElementById('box1');
div.style.display = 'none';
}
</script>
</head>
<body>
<table>
<tr>
<td onmouseover="showMenu()" >username</td>
</tr>
</table>
<div id="box1" onmouseout="hideMenu()">
Logout<br>
</div>
</body>
</html>
UPDATE- this should fix the "jumping" problem:
<html>
<head>
<style type="text/css">
.username {
width: 100px;
border: 1px solid #ff0000;
padding: 3px;
text-align: center;
position: relative;
display: inline-block;
}
#box1 {
display: none;
text-align: center;
position: absolute;
background-color: #ccc;
}
</style>
<script>
showMenu = function() {
var div = document.getElementById('box1');
div.style.display = 'block';
}
hideMenu = function() {
var div = document.getElementById('box1');
div.style.display = 'none';
}
</script>
</head>
<body>
<table>
<tr>
<td colspan=3 align="left">
<img src=":">
</td>
<td colspan=6 valign="bottom" align="right">Menu1 Menu2 Menu3 Menu4 Menu5 Menu6 Menu7
<div class="username" onmouseover="showMenu();" onmouseout="hideMenu();">Username
<span id="box1">
Logout
</span>
</div>
</td>
</tr>
<tr>
<td colspan=9>
<hr color="red">
</td>
</tr>
</table>
</body>
</html>
The problem is that absolute positioning doesn't work the same inside of a span than as it does a div. So I had to change the "username" span to a div and use absolute position for the "box1" span. You could even change the "box1" span to a div as well so it occupies the whole width possible of the "username" div. Let me know how this one goes!
Here is the version where it jumps up. If you put position: absolute; in the style tag the menu extends one more cell to the right past the other columns...
.username {
}
#box1 {
display: none;
}
</style>
<script>
showMenu = function() {
var div = document.getElementById('box1');
div.style.display = 'block';
}
hideMenu = function() {
var div = document.getElementById('box1');
div.style.display = 'none';
}
</script>
</head>
<body>
<table><tr>
<td colspan=3 align="left"><img src=":"></td>
<td colspan=6 valign="bottom" align="right">Menu1 Menu2 Menu3 Menu4 Menu5
Menu6 Menu7 <span class="username" onmouseover="showMenu();"
onmouseout="hideMenu();">Username<span id="box1">
Logout
</span>
</span></b></td></tr>
<tr><td colspan=9><hr color = "red"></td></tr>
</table>
</body>
</html>
I've been working on an ASP.net project that uses custom 'modal dialogs'. I use scare quotes here because I understand that the 'modal dialog' is simply a div in my html document that is set to appear "on top" of the rest of the document and is not a modal dialog in the true sense of the word.
In many parts of the web site, I have code that looks like this:
var warning = 'Are you sure you want to do this?';
if (confirm(warning)) {
// Do something
}
else {
// Do something else
}
This is okay, but it would be nice to make the confirm dialog match the style of the rest of the page.
However, since it is not a true modal dialog, I think that I need to write something like this: (I use jQuery-UI in this example)
<div id='modal_dialog'>
<div class='title'>
</div>
<input type='button' value='yes' id='btnYes' />
<input type='button' value='no' id='btnNo' />
</div>
<script>
function DoSomethingDangerous() {
var warning = 'Are you sure you want to do this?';
$('.title').html(warning);
var dialog = $('#modal_dialog').dialog();
function Yes() {
dialog.dialog('close');
// Do something
}
function No() {
dialog.dialog('close');
// Do something else
}
$('#btnYes').click(Yes);
$('#btnNo').click(No);
}
Is this a good way to accomplish what I want, or is there a better way?
You might want to consider abstracting it out into a function like this:
function dialog(message, yesCallback, noCallback) {
$('.title').html(message);
var dialog = $('#modal_dialog').dialog();
$('#btnYes').click(function() {
dialog.dialog('close');
yesCallback();
});
$('#btnNo').click(function() {
dialog.dialog('close');
noCallback();
});
}
You can then use it like this:
dialog('Are you sure you want to do this?',
function() {
// Do something
},
function() {
// Do something else
}
);
SweetAlert
You should take a look at SweetAlert as an option to save some work. It's beautiful from the default state and is highly customizable.
Confirm Example
sweetAlert(
{
title: "Are you sure?",
text: "You will not be able to recover this imaginary file!",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Yes, delete it!"
},
deleteIt()
);
To enable you to use the confirm box like the normal confirm dialog, I would use Promises which will enable you to await on the result of the outcome and then act on this, rather than having to use callbacks.
This will allow you to follow the same pattern you have in other parts of your code with code such as...
const confirm = await ui.confirm('Are you sure you want to do this?');
if(confirm){
alert('yes clicked');
} else{
alert('no clicked');
}
See codepen for example, or run the snippet below.
https://codepen.io/larnott/pen/rNNQoNp
const ui = {
confirm: async (message) => createConfirm(message)
}
const createConfirm = (message) => {
return new Promise((complete, failed)=>{
$('#confirmMessage').text(message)
$('#confirmYes').off('click');
$('#confirmNo').off('click');
$('#confirmYes').on('click', ()=> { $('.confirm').hide(); complete(true); });
$('#confirmNo').on('click', ()=> { $('.confirm').hide(); complete(false); });
$('.confirm').show();
});
}
const saveForm = async () => {
const confirm = await ui.confirm('Are you sure you want to do this?');
if(confirm){
alert('yes clicked');
} else{
alert('no clicked');
}
}
body {
margin: 0px;
font-family: "Arial";
}
.example {
padding: 20px;
}
input[type=button] {
padding: 5px 10px;
margin: 10px 5px;
border-radius: 5px;
cursor: pointer;
background: #ddd;
border: 1px solid #ccc;
}
input[type=button]:hover {
background: #ccc;
}
.confirm {
display: none;
}
.confirm > div:first-of-type {
position: fixed;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
top: 0px;
left: 0px;
}
.confirm > div:last-of-type {
padding: 10px 20px;
background: white;
position: absolute;
width: auto;
height: auto;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border-radius: 5px;
border: 1px solid #333;
}
.confirm > div:last-of-type div:first-of-type {
min-width: 150px;
padding: 10px;
}
.confirm > div:last-of-type div:last-of-type {
text-align: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="example">
<input type="button" onclick="saveForm()" value="Save" />
</div>
<!-- Hidden confirm markup somewhere at the bottom of page -->
<div class="confirm">
<div></div>
<div>
<div id="confirmMessage"></div>
<div>
<input id="confirmYes" type="button" value="Yes" />
<input id="confirmNo" type="button" value="No" />
</div>
</div>
</div>
I would use the example given on jQuery UI's site as a template:
$( "#modal_dialog" ).dialog({
resizable: false,
height:140,
modal: true,
buttons: {
"Yes": function() {
$( this ).dialog( "close" );
},
"No": function() {
$( this ).dialog( "close" );
}
}
});
var confirmBox = '<div class="modal fade confirm-modal">' +
'<div class="modal-dialog modal-sm" role="document">' +
'<div class="modal-content">' +
'<button type="button" class="close m-4 c-pointer" data-dismiss="modal" aria-label="Close">' +
'<span aria-hidden="true">×</span>' +
'</button>' +
'<div class="modal-body pb-5"></div>' +
'<div class="modal-footer pt-3 pb-3">' +
'OK' +
'<button type="button" class="btn btn-secondary abortBtn btn-sm" data-dismiss="modal">Abbrechen</button>' +
'</div>' +
'</div>' +
'</div>' +
'</div>';
var dialog = function(el, text, trueCallback, abortCallback) {
el.click(function(e) {
var thisConfirm = $(confirmBox).clone();
thisConfirm.find('.modal-body').text(text);
e.preventDefault();
$('body').append(thisConfirm);
$(thisConfirm).modal('show');
if (abortCallback) {
$(thisConfirm).find('.abortBtn').click(function(e) {
e.preventDefault();
abortCallback();
$(thisConfirm).modal('hide');
});
}
if (trueCallback) {
$(thisConfirm).find('.yesBtn').click(function(e) {
e.preventDefault();
trueCallback();
$(thisConfirm).modal('hide');
});
} else {
if (el.prop('nodeName') == 'A') {
$(thisConfirm).find('.yesBtn').attr('href', el.attr('href'));
}
if (el.attr('type') == 'submit') {
$(thisConfirm).find('.yesBtn').click(function(e) {
e.preventDefault();
el.off().click();
});
}
}
$(thisConfirm).on('hidden.bs.modal', function(e) {
$(this).remove();
});
});
}
// custom confirm
$(function() {
$('[data-confirm]').each(function() {
dialog($(this), $(this).attr('data-confirm'));
});
dialog($('#customCallback'), "dialog with custom callback", function() {
alert("hi there");
});
});
.test {
display:block;
padding: 5p 10px;
background:orange;
color:white;
border-radius:4px;
margin:0;
border:0;
width:150px;
text-align:center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
example 1
<a class="test" href="http://example" data-confirm="do you want really leave the website?">leave website</a><br><br>
example 2
<form action="">
<button class="test" type="submit" data-confirm="send form to delete some files?">delete some files</button>
</form><br><br>
example 3
<span class="test" id="customCallback">with callback</span>
One other way would be using colorbox
function createConfirm(message, okHandler) {
var confirm = '<p id="confirmMessage">'+message+'</p><div class="clearfix dropbig">'+
'<input type="button" id="confirmYes" class="alignleft ui-button ui-widget ui-state-default" value="Yes" />' +
'<input type="button" id="confirmNo" class="ui-button ui-widget ui-state-default" value="No" /></div>';
$.fn.colorbox({html:confirm,
onComplete: function(){
$("#confirmYes").click(function(){
okHandler();
$.fn.colorbox.close();
});
$("#confirmNo").click(function(){
$.fn.colorbox.close();
});
}});
}
Faced with the same problem, I was able to solve it using only vanilla JS, but in an ugly way. To be more accurate, in a non-procedural way. I removed all my function parameters and return values and replaced them with global variables, and now the functions only serve as containers for lines of code - they're no longer logical units.
In my case, I also had the added complication of needing many confirmations (as a parser works through a text). My solution was to put everything up to the first confirmation in a JS function that ends by painting my custom popup on the screen, and then terminating.
Then the buttons in my popup call another function that uses the answer and then continues working (parsing) as usual up to the next confirmation, when it again paints the screen and then terminates. This second function is called as often as needed.
Both functions also recognize when the work is done - they do a little cleanup and then finish for good. The result is that I have complete control of the popups; the price I paid is in elegance.
I managed to find the solution that will allow you to do this using default confirm() with minimum of changes if you have a lot of confirm() actions through out you code. This example uses jQuery and Bootstrap but the same thing can be accomplished using other libraries as well. You can just copy paste this and it should work right away
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Project Title</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<h1>Custom Confirm</h1>
<button id="action"> Action </button>
<button class='another-one'> Another </button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script type="text/javascript">
document.body.innerHTML += `<div class="modal fade" style="top:20vh" id="customDialog" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" id='dialog-cancel' class="btn btn-secondary">Cancel</button>
<button type="button" id='dialog-ok' class="btn btn-primary">Ok</button>
</div>
</div>
</div>
</div>`;
function showModal(text) {
$('#customDialog .modal-body').html(text);
$('#customDialog').modal('show');
}
function startInterval(element) {
interval = setInterval(function(){
if ( window.isConfirmed != null ) {
window.confirm = function() {
return window.isConfirmed;
}
elConfrimInit.trigger('click');
clearInterval(interval);
window.isConfirmed = null;
window.confirm = function(text) {
showModal(text);
startInterval();
}
}
}, 500);
}
window.isConfirmed = null;
window.confirm = function(text,elem = null) {
elConfrimInit = elem;
showModal(text);
startInterval();
}
$(document).on('click','#dialog-ok', function(){
isConfirmed = true;
$('#customDialog').modal('hide');
});
$(document).on('click','#dialog-cancel', function(){
isConfirmed = false;
$('#customDialog').modal('hide');
});
$('#action').on('click', function(e) {
if ( confirm('Are you sure?',$(this)) ) {
alert('confrmed');
}
else {
alert('not confimed');
}
});
$('.another-one').on('click', function(e) {
if ( confirm('Are really, really, really sure ? you sure?',$(this)) ) {
alert('confirmed');
}
else {
alert('not confimed');
}
});
</script>
</body>
</html>
This is the whole example. After you implement it you will be able to use it like this:
if ( confirm('Are you sure?',$(this)) )
I created a js file with below given code and named it newconfirm.js
function confirm(q,yes){
var elem='<div class="modal fade" id="confirmmodal" role="dialog" style="z-index: 1500;">';
elem+='<div class="modal-dialog" style="width: 25vw;">';
elem+='<div class="modal-content">';
elem+='<div class="modal-header" style="padding:8px;background-color:lavender;">';
elem+='<button type="button" class="close" data-dismiss="modal">×</button>';
elem+='<h3 class="modal-title" style="color:black;">Message</h3></div>';
elem+='<div class="modal-body col-xs-12" style="padding:;background-color: ghostwhite;height:auto;">';
elem+='<div class="col-xs-3 pull-left" style="margin-top: 0px;">';
elem+='<img class="img-rounded" src="msgimage.jpg" style="width: 49%;object-fit: contain;" /></div><div class="col-xs-9 pull-left "><p class="aconfdiv"></p></div></div>';
elem+='<div class="modal-footer col-xs-12" style="padding:6px;background-color:lavender;"><div class="btn btn-sm btn-success yes pull-left">Yes</div><button type="button" class="btn btn-default btn-sm" data-dismiss="modal">No</button></div></div></div></div>';
$('body').append(elem);
$('body').append('<div class="lead cresp"></div>');
$('.aconfdiv').html(q);
$('#confirmmodal').modal('show');
$('.yes').on('click',function(){
$('body').find('.cresp').html('Yes');
$('#confirmmodal').modal('hide');
yes();
})
}
and in my main php file calling confirm in the javascript like this
$('.cnf').off().on('click',function(){
confirm("Do you want to save the data to Database?<br />Kindly check the data properly as You cannot undo this action",function(){
var resp=$('body').find('.cresp').html();
$('body').find('.cresp').remove();
if(resp=='Yes'){
alert("You clicked on Yes Bro.....")
}
});
})