Hide color-picker spectrum when using `choices`.
This seems impossible to be done with the current jscolor library.
I start to consider the idea to switch to another color picker with the same UX and a similar implementation.
Here the list of candidates:
* [Coloris](https://github.com/mdbassit/Coloris)
That would be nice. I came here to inspect how hard it would be to add hsl support as I have my palette defined in that.
Moving away from JSColor would be good as whilst this package is MIT Licensed JSColor is not. It's only GNU GPL v3 for opensource packages any commercial or even private projects would not be able to use this library due to their license.
@StevenMapes I'm aware of this limitation, unfortunately at the moment I have not the time for working on it.
I created this discussion #83.
Here is a workaround:
const startObserving = (domNode) => {
const observer = new MutationObserver(mutations => {
mutations.forEach(function (mutation) {
const element = Array.from(mutation.addedNodes).filter(
element => {
if (element.classList) {
return element.classList.contains('jscolor-picker-wrap');
} else {
return false;
}
},
);
if (element.length) {
const wrapper = element[0]
const picker = document.querySelector('.jscolor-picker')
const palette = document.querySelector('.jscolor-palette')
document.querySelectorAll(".jscolor-picker > div:not(.jscolor-palette)").forEach((el) => picker.removeChild(el))
wrapper.style.height = `${wrapper.offsetHeight - palette.offsetTop + 20}px`
picker.style.height = `${picker.offsetHeight - palette.offsetTop + 20}px`
palette.style.top = `20px`
}
});
});
observer.observe(domNode, {
childList: true,
attributes: true,
characterData: true,
subtree: true,
});
return observer;
};
startObserving(document.body, 'jscolor-picker'); // Replace the first parameter with the tag where the jscolor component is called.
Since the jscolor library destroys and recreates the HTML node everytime it's activated, we have to use the MutationObserver to listen for it's creation. This code listens to the HTML node where the jscolor is placed at and removes every child element (which includes the color picker and slider) except for the color palette. Then, it resizes the surrounding divs to shrink to exactly the height of the color palette.
@Nicholas-Toh great workaround, thanks for sharing it!
Considering how JSColor creates/destroys the element I think that this is the only possible solution.
@Nicholas-Toh I tested your snippet is an admin page with many colorfields because I wanted to implement it, but it seems to have many issues:
- it ignores the fact that it should work only on fields that are using the
choicesoptions. - it doesn't work correctly depending on the position where the color-picker appears
Here an improved version of your script in case you would like to adjust it / submit a PR:
document.addEventListener('DOMContentLoaded', function () {
const startObserving = (domNode) => {
const observer = new MutationObserver(mutations => {
mutations.forEach(function (mutation) {
const element = Array.from(mutation.addedNodes).find(
element => element.classList && element.classList.contains('jscolor-picker-wrap')
);
if (element) {
const wrapper = element;
const picker = document.querySelector('.jscolor-picker');
const palette = document.querySelector('.jscolor-palette');
document.querySelectorAll(".jscolor-picker > div:not(.jscolor-palette)").forEach((el) => el.remove());
const newHeight = wrapper.offsetHeight - palette.offsetTop + 20;
wrapper.style.height = `${newHeight}px`;
picker.style.height = `${newHeight}px`;
palette.style.top = '20px';
}
});
});
observer.observe(domNode, {
childList: true,
attributes: true,
characterData: true,
subtree: true,
});
return observer;
};
startObserving(document.body);
});