I am working with Bootstrap 4 and the Bootstrap colorpicker (https://itsjavi.com/bootstrap-colorpicker/) to create a colorpicker in a popup that contains a field in which the color code can be set. However, when the popover is opened, the input (#color-value) seems like it can't be edited. From debugging it's clear that it loses focus as soon as it gains focus (the 'focus' and 'focusout' below are logged right below each other. Research shows that it must have something to do with Bootstrap, but I can't seem to find a workaround. Has anyone got a solution/workaround?
I tried unbinding all the focus, focusout, blur, ... eventhandlers for the input, as well as any combination of preventdefault and stoppropagation for the eventlisteners, but all without success
Here's the relevant code
HTML:
<div class="tag col-md-4" data-tag-id="1">
<div class="form-group input-group colorpicker-container">
<input name="section-1-tag-1" type="text" class="form-control language-field" placeholder="Tag">
<div class="input-group-append"><input name="section-1-tag-1-border-color" type="text" class="form-control language-field border-color no-auto-show colorpicker-element" ><a class="btn btn-icon btn-sm btn-show-colorpicker"><i class="far fa-droplet"></i></a><a class="btn btn-small btn-round btn-icon btn-danger btn-delete-tag" data-button-initiated="true"><i class="now-ui-icons ui-1_simple-remove"></i></a><a class="btn btn-icon btn-sm btn-reset-color"><i class="far fa-refresh"></i></a></div>
</div>
</div>
JS:
var color = false;
if($('.border-color').val()) {
color = $('.border-color').val();
}
$('.border-color').colorpicker(
{
//container: true, // tried turning this off and on, no success
useAlpha: true,
format: "rgba",
popover: {
placement: 'top'
},
color: color,
template:
'<div class="colorpicker">' +
'<div class="colorpicker-saturation"><i class="colorpicker-guide"></i></div>' +
'<div class="colorpicker-hue"><i class="colorpicker-guide"></i></div>' +
'<div class="colorpicker-alpha">' +
' <div class="colorpicker-alpha-color"></div>' +
' <i class="colorpicker-guide"></i>' +
"</div>" +
'<div class="colorpicker-bar has-input">' +
' <div class="input-group">' +
' <input type="text" id="color-value" class="form-control input-block color-io" />' +
" </div>" +
"</div>" +
"</div>"
}
).on("colorpickerShow", function (e) {
console.log('colorpickerShow');
var element = e.colorpicker.element;
var io = $('#' + element.attr('aria-describedby') + ' #color-value');
var defaultColor = e.color.string();
if(element.val()) {
e.colorpicker.setValue(element.val());
$(element).siblings(".btn-show-colorpicker").find("i").css("color", element.val());
$(element).siblings(".btn-reset-color").show();
io.val(element.val());
} else {
$(element).siblings(".btn-reset-color").hide();
}
io.on('focus keydown mousedown active', function(e) {
e.stopPropagation();
e.preventDefault();
console.log(e);
console.log('focus');
});
io.on('focusout blur', function() {
e.stopPropagation();
//e.preventDefault();
console.log(e);
console.log('focusout');
});
element.on("change keyup", function () {
e.colorpicker.setValue(element.val());
$(element).siblings(".btn-reset-color").show();
});
io.on("change", function () {
e.colorpicker.setValue(io.val());
if($(this).val()) {
e.colorpicker.setValue('');
$(element).siblings(".btn-reset-color").hide();
} else {
e.colorpicker.setValue($(this).val());
$(element).siblings(".btn-reset-color").show();
}
});
})
What the popover's html actually looks like:
<div class="popover colorpicker-bs-popover fade show bs-popover-bottom" role="tooltip" id="popover467222" style="position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(268px, 159px, 0px);" x-placement="bottom">
<div class="arrow" style="left: 84px;"></div>
<h3 class="popover-header"></h3>
<div class="popover-body">
<div class="colorpicker colorpicker-with-alpha colorpicker-popup colorpicker-bs-popover-content colorpicker-visible">
<div class="colorpicker-saturation" style="background-color: rgb(255, 0, 0);"><i class="colorpicker-guide" style="top: 42px; left: 35px;"></i></div>
<div class="colorpicker-hue"><i class="colorpicker-guide" style="top: 126px;"></i></div>
<div class="colorpicker-alpha">
<div class="colorpicker-alpha-color" style="background: linear-gradient(rgb(170, 123, 123) 0%, transparent 100%);"></div>
<i class="colorpicker-guide" style="top: 0px;"></i></div>
<div class="colorpicker-bar has-input">
<div class="input-group">
<input type="text" id="color-value" class="form-control input-block color-io">
</div>
</div>
<div class="colorpicker-bar colorpicker-preview">
<div style="background-color: rgb(170, 123, 123); color: black;">rgb(170, 123, 123)</div>
</div>
</div>
</div>
</div>
BELOW YOU CAN FINDE A WORKING SNIPPET
$(document).ready(function() {
var color = false;
if($('.border-color').val()) {
color = $('.border-color').val();
}
$('.border-color').colorpicker(
{
//container: true, // tried turning this off and on, no success
useAlpha: true,
format: "rgba",
popover: {
placement: 'top'
},
color: color,
template:
'<div class="colorpicker">' +
'<div class="colorpicker-saturation"><i class="colorpicker-guide"></i></div>' +
'<div class="colorpicker-hue"><i class="colorpicker-guide"></i></div>' +
'<div class="colorpicker-alpha">' +
' <div class="colorpicker-alpha-color"></div>' +
' <i class="colorpicker-guide"></i>' +
"</div>" +
'<div class="colorpicker-bar has-input">' +
' <div class="input-group">' +
' <input type="text" id="color-value" class="form-control input-block color-io" />' +
" </div>" +
"</div>" +
"</div>"
}
).on("colorpickerShow", function (e) {
console.log('colorpickerShow');
var element = e.colorpicker.element;
var io = $('#' + element.attr('aria-describedby') + ' #color-value');
var defaultColor = e.color.string();
if(element.val()) {
e.colorpicker.setValue(element.val());
$(element).siblings(".btn-show-colorpicker").find("i").css("color", element.val());
$(element).siblings(".btn-reset-color").show();
io.val(element.val());
} else {
$(element).siblings(".btn-reset-color").hide();
}
io.on('focus keydown mousedown active', function(e) {
e.stopPropagation();
e.preventDefault();
console.log(e);
console.log('focus');
});
io.on('focusout blur', function() {
e.stopPropagation();
//e.preventDefault();
console.log(e);
console.log('focusout');
});
element.on("change keyup", function () {
e.colorpicker.setValue(element.val());
$(element).siblings(".btn-reset-color").show();
});
io.on("change", function () {
e.colorpicker.setValue(io.val());
if($(this).val()) {
e.colorpicker.setValue('');
$(element).siblings(".btn-reset-color").hide();
} else {
e.colorpicker.setValue($(this).val());
$(element).siblings(".btn-reset-color").show();
}
});
});
});
body {
padding: 50px;
min-height: 500px;
}
.colorpicker-container .input-group-append .colorpicker-element {
position: absolute;
left: 0;
top: 0;
right: auto;
bottom: 0;
width: 30px;
height: 100%;
opacity: 0;
z-index: 3;
cursor: pointer;
padding: 0;
}
<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://youreka-virtualtours.be/dashboard/assets/js/core/popper.min.js"></script>
<script src="https://youreka-virtualtours.be/dashboard/assets/js/core/bootstrap.min.js"></script>
<script src="https://youreka-virtualtours.be/dashboard/assets/js/plugins/jquery.bootstrap-wizard.js"></script>
<script src="https://youreka-virtualtours.be/dashboard/assets/js/now-ui-dashboard.js"></script>
<link href="https://youreka-virtualtours.be/dashboard/assets/css/now-ui-dashboard.css" rel="stylesheet"/>
<link href="https://youreka-virtualtours.be/dashboard/assets/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://youreka-virtualtours.be/libraries/bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css" rel="stylesheet"/>
<script src="https://youreka-virtualtours.be/libraries/bootstrap-colorpicker/dist/js/bootstrap-colorpicker.js"></script>
<script src="https://kit.fontawesome.com/eecbfb86a5.js" crossorigin="anonymous"></script>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
<div class="tag col-md-4" data-tag-id="1">
<div class="form-group input-group colorpicker-container">
<input name="section-1-tag-1" type="text" class="form-control language-field" placeholder="Tag">
<div class="input-group-append"><input name="section-1-tag-1-border-color" type="text" class="form-control language-field border-color no-auto-show" ><a class="btn btn-icon btn-sm btn-show-colorpicker"><i class="far fa-droplet"></i></a><a class="btn btn-small btn-round btn-icon btn-danger btn-delete-tag" data-button-initiated="true"><i class="now-ui-icons ui-1_simple-remove"></i></a><a class="btn btn-icon btn-sm btn-reset-color"><i class="far fa-refresh"></i></a></div>
</div>
</div>
</body>
</html>
This is pretty ugly but I think you can use it as a starting point. I put the template in a template element. I then added a second input group and put a color attribute on each. This is where, when the button is clicked those yellow and blue come from - but shows you how to find them and do that.
I also added a target element so you can see how to apply the colors to another element as border and background - just for an example.
Not super clean but something to build from perhaps.