Skip to content

Instantly share code, notes, and snippets.

@YuriGor
Last active November 6, 2019 05:46
Show Gist options
  • Save YuriGor/c413b6d5b6e82554b8a37400a8f6580e to your computer and use it in GitHub Desktop.
Save YuriGor/c413b6d5b6e82554b8a37400a8f6580e to your computer and use it in GitHub Desktop.
vanilla-picker as absolutely auto-positioned dialog added to document.body - WIP: https://github.com/Sphinxxxx/vanilla-picker/issues/24
import colorDialog from './vanillaColorDialog';
document.getElementById('some-other-button').addEventListener('click',function(e){
// auto position is by default
colorDialog(e, '#000000'/* ,{ popup: 'auto', popup: ['right', 'left', 'bottom', 'top'], otherVanillaOption: 'whatever' }*/).then(console.log);
});
// https://github.com/Sphinxxxx/vanilla-picker/issues/24
// https://jsfiddle.net/9g4nsdz3/2/
import merge from 'lodash-es/merge';
import each from 'lodash-es/each';
import isArray from 'lodash-es/isArray';
import Picker from 'vanilla-picker';
const settings = {
layout: 'default',
alpha: true,
editor: true,
editorFormat: 'hex',
cancelButton: false,
popup: 'auto',
};
const picker = new Picker({
parent: document.body,
});
const placementStyle = document.body.appendChild(
document.createElement('style')
);
picker.originalOpenHandler = picker.openHandler;
picker.openHandler = function() {};
export default function showColorDialog(e, currentColor, options) {
return new Promise((resolve) => {
const clickedElement = e.target;
options = merge({}, settings, options);
if (options.color || options.colour) {
throw new Error('Dont set color in options, use second arg instead.');
}
var popups = options.popup;
if (isArray(popups)) {
options.popup = options.popup[0];
} else {
popups = [popups];
}
if (options.popup == 'auto') {
options.popup = 'right';
popups = ['right', 'left', 'bottom', 'top'];
}
setPosition(popups[0], clickedElement);
picker.setOptions(options);
console.log('setOptions', options);
picker.setColor(currentColor);
picker.onClose = (color) => {
color.hexOrRgba = () => {
var hexOrRgba = color.hex.toLowerCase();
if (_.endsWith(hexOrRgba, 'ff')) {
hexOrRgba = hexOrRgba.substr(0, 7);
} else {
hexOrRgba = color.rgbaString;
}
return hexOrRgba;
};
resolve(color);
};
picker.originalOpenHandler(e);
if (!options.alpha) {
picker.domElement.classList.add('no_alpha');
} else {
picker.domElement.classList.remove('no_alpha');
}
if (!options.editor) {
picker.domElement.classList.add('no_editor');
} else {
picker.domElement.classList.remove('no_editor');
}
if (!options.cancelButton) {
picker.domElement.classList.add('no_cancel');
} else {
picker.domElement.classList.remove('no_cancel');
}
autoPosition(popups, options, clickedElement);
});
}
function setPosition(popup, clickedElement) {
const bounds = clickedElement.getBoundingClientRect();
let top, left, translate;
switch (popup) {
case 'right':
left = bounds.right + 15 + window.pageXOffset + 'px';
top = bounds.bottom - 15 + window.pageYOffset + 'px';
translate = '0, 0';
break;
case 'left':
left = bounds.left - 45 + window.pageXOffset + 'px';
top = bounds.bottom - 15 + window.pageYOffset + 'px';
translate = '-100%, 0';
break;
case 'top':
left = bounds.left - 15 + window.pageXOffset + 'px';
top = bounds.top - 45 + window.pageYOffset + 'px';
translate = '0, -100%';
break;
case 'bottom':
left = bounds.left - 15 + window.pageXOffset + 'px';
top = bounds.bottom + 15 + window.pageYOffset + 'px';
translate = '0, 0';
break;
}
placementStyle.textContent = `
.picker_wrapper.popup.popup_${popup} {
top: ${top};
left: ${left};
transform: translate(${translate});
bottom: auto;
right: auto;
}`;
console.log('style updated', placementStyle);
}
function autoPosition(popups, options, clickedElement) {
let pickerBounds = picker.domElement.getBoundingClientRect();
if (doesPickerFit(pickerBounds)) return;
each(popups, (popup) => {
console.log('autoPosition', popup);
if (popup != options.popup) {
console.log('switch to new ' + popup + ' position');
options.popup = popup;
setPosition(popup, clickedElement);
picker.setOptions(options);
console.log('setOptions', options);
picker.show();
pickerBounds = picker.domElement.getBoundingClientRect();
}
if (doesPickerFit(pickerBounds)) {
console.log('picker fits ', pickerBounds);
return false;
} else {
console.log("picker doesn't fit ", pickerBounds);
}
});
}
function doesPickerFit(bounds) {
return (
bounds.top >= 0 &&
bounds.right <= window.innerWidth &&
bounds.bottom <= window.innerHeight &&
bounds.left >= 0
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment