Fixed colour picker issues and integrated into main JS file.
This commit is contained in:
parent
433b00e93b
commit
0b816b2bd4
8 changed files with 511 additions and 643 deletions
505
public/picker.js
505
public/picker.js
|
@ -1,505 +0,0 @@
|
||||||
var FwColourPicker = function(callback, options, colour, onClose) {
|
|
||||||
if(typeof callback !== 'function')
|
|
||||||
return;
|
|
||||||
if(typeof colour !== 'number')
|
|
||||||
colour = parseInt(colour || 0);
|
|
||||||
if(typeof options !== 'object')
|
|
||||||
options = {};
|
|
||||||
|
|
||||||
var readThres = 168,
|
|
||||||
lumiRed = .299,
|
|
||||||
lumiGreen = .587,
|
|
||||||
lumiBlue = .114;
|
|
||||||
|
|
||||||
var extractRGB = function(raw) {
|
|
||||||
return [
|
|
||||||
(raw >> 16) & 0xFF,
|
|
||||||
(raw >> 8) & 0xFF,
|
|
||||||
raw & 0xFF,
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
var calcLumi = function(raw) {
|
|
||||||
var rgb = extractRGB(raw);
|
|
||||||
return rgb[0] * lumiRed
|
|
||||||
+ rgb[1] * lumiGreen
|
|
||||||
+ rgb[2] * lumiBlue;
|
|
||||||
};
|
|
||||||
|
|
||||||
var textColour = function(raw) {
|
|
||||||
return calcLumi(raw) > readThres ? 0 : 0xFFFFFF;
|
|
||||||
};
|
|
||||||
|
|
||||||
var weightNum = function(n1, n2, w) {
|
|
||||||
w = Math.min(1, Math.max(0, w));
|
|
||||||
return Math.round((n1 * w) + (n2 * (1 - w)));
|
|
||||||
};
|
|
||||||
|
|
||||||
var weightColour = function(c1, c2, w) {
|
|
||||||
c1 = extractRGB(c1);
|
|
||||||
c2 = extractRGB(c2);
|
|
||||||
return (weightNum(c1[0], c2[0], w) << 16)
|
|
||||||
| (weightNum(c1[1], c2[1], w) << 8)
|
|
||||||
| weightNum(c1[2], c2[2], w);
|
|
||||||
};
|
|
||||||
|
|
||||||
var shadeColour = function(raw, offset) {
|
|
||||||
if(offset == 0)
|
|
||||||
return raw;
|
|
||||||
|
|
||||||
var dir = 0xFFFFFF;
|
|
||||||
if(offset < 0) {
|
|
||||||
dir = 0;
|
|
||||||
offset *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return weightColour(dir, raw, offset);
|
|
||||||
};
|
|
||||||
|
|
||||||
var hexFormat = FwColourPicker.hexFormat;
|
|
||||||
|
|
||||||
var verifyOption = function(name, type, def) {
|
|
||||||
if(typeof options[name] !== type)
|
|
||||||
options[name] = def;
|
|
||||||
};
|
|
||||||
|
|
||||||
verifyOption('posX', 'number', -1);
|
|
||||||
verifyOption('posY', 'number', -1);
|
|
||||||
verifyOption('presets', 'object', []);
|
|
||||||
verifyOption('showPresetsTab', 'boolean', options.presets.length > 0);
|
|
||||||
verifyOption('showGridTab', 'boolean', true);
|
|
||||||
verifyOption('showSlidersTab', 'boolean', true);
|
|
||||||
verifyOption('showHexValue', 'boolean', true);
|
|
||||||
verifyOption('showRawValue', 'boolean', true);
|
|
||||||
verifyOption('autoClose', 'boolean', true);
|
|
||||||
|
|
||||||
var onColourChange = [];
|
|
||||||
var runOnColourChange = function() {
|
|
||||||
var text = textColour(colour);
|
|
||||||
for(var i = 0; i < onColourChange.length; ++i)
|
|
||||||
onColourChange[i](colour, text);
|
|
||||||
};
|
|
||||||
|
|
||||||
var setColour = function(raw) {
|
|
||||||
colour = parseInt(raw || 0) & 0xFFFFFF;
|
|
||||||
runOnColourChange();
|
|
||||||
};
|
|
||||||
|
|
||||||
var apply = function() {
|
|
||||||
callback(pub, colour);
|
|
||||||
if(options.autoClose)
|
|
||||||
close();
|
|
||||||
};
|
|
||||||
|
|
||||||
var cancel = function() {
|
|
||||||
callback(pub, null);
|
|
||||||
if(options.autoClose)
|
|
||||||
close();
|
|
||||||
};
|
|
||||||
|
|
||||||
var close = function() {
|
|
||||||
if(onClose && onClose())
|
|
||||||
return;
|
|
||||||
container.parentNode.removeChild(container);
|
|
||||||
};
|
|
||||||
|
|
||||||
var height = 96;
|
|
||||||
|
|
||||||
var container = document.createElement('div');
|
|
||||||
container.className = 'fw-colour-picker';
|
|
||||||
onColourChange.push(function(colour) {
|
|
||||||
container.style.borderColor = hexFormat(colour);
|
|
||||||
});
|
|
||||||
|
|
||||||
var form = document.createElement('form');
|
|
||||||
form.className = 'fw-colour-picker-form';
|
|
||||||
container.appendChild(form);
|
|
||||||
|
|
||||||
form.onsubmit = function(ev) {
|
|
||||||
ev.preventDefault();
|
|
||||||
apply();
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
var tabs = {};
|
|
||||||
var activeTab = undefined;
|
|
||||||
onColourChange.push(function(colour, text) {
|
|
||||||
if(activeTab) {
|
|
||||||
activeTab.b.style.background = hexFormat(colour);
|
|
||||||
activeTab.b.style.borderColor = hexFormat(colour);
|
|
||||||
activeTab.b.style.color = hexFormat(text);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var tabbed = document.createElement('div');
|
|
||||||
tabbed.className = 'fw-colour-picker-tabbed';
|
|
||||||
|
|
||||||
var tabbedContainer = document.createElement('div');
|
|
||||||
tabbedContainer.className = 'fw-colour-picker-tabbed-container';
|
|
||||||
tabbed.appendChild(tabbedContainer);
|
|
||||||
onColourChange.push(function(colour) {
|
|
||||||
tabbedContainer.style.borderColor = hexFormat(colour);
|
|
||||||
});
|
|
||||||
|
|
||||||
var tabbedList = document.createElement('div');
|
|
||||||
tabbedList.className = 'fw-colour-picker-tabbed-list';
|
|
||||||
tabbed.appendChild(tabbedList);
|
|
||||||
|
|
||||||
var switchTab = function(id) {
|
|
||||||
if(activeTab == tabs[id])
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(activeTab) {
|
|
||||||
activeTab.c.classList.remove('fw-colour-picker-tab-container-active');
|
|
||||||
activeTab.b.classList.remove('fw-colour-picker-tab-button-active');
|
|
||||||
activeTab.b.style.background = '';
|
|
||||||
activeTab.b.style.borderColor = '';
|
|
||||||
activeTab.b.style.color = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
activeTab = tabs[id] || undefined;
|
|
||||||
|
|
||||||
if(activeTab) {
|
|
||||||
activeTab.c.classList.add('fw-colour-picker-tab-container-active');
|
|
||||||
activeTab.b.classList.add('fw-colour-picker-tab-button-active');
|
|
||||||
activeTab.b.style.background = hexFormat(colour);
|
|
||||||
activeTab.b.style.borderColor = hexFormat(colour);
|
|
||||||
activeTab.b.style.color = hexFormat(textColour(colour));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var createTab = function(id, name, construct) {
|
|
||||||
var tabContainer = construct();
|
|
||||||
tabContainer.className = 'fw-colour-picker-tab-container fw-colour-picker-tab-' + id + '-container';
|
|
||||||
tabbedContainer.appendChild(tabContainer);
|
|
||||||
|
|
||||||
var tabButton = document.createElement('input');
|
|
||||||
tabButton.type = 'button';
|
|
||||||
tabButton.value = name;
|
|
||||||
tabButton.className = 'fw-colour-picker-tab-button fw-colour-picker-tab-' + id + '-button';
|
|
||||||
tabButton.onclick = function() { switchTab(id); };
|
|
||||||
tabbedList.appendChild(tabButton);
|
|
||||||
|
|
||||||
tabs[id] = { c: tabContainer, b: tabButton };
|
|
||||||
|
|
||||||
if(activeTab === undefined) {
|
|
||||||
activeTab = tabs[id];
|
|
||||||
tabContainer.className += ' fw-colour-picker-tab-container-active';
|
|
||||||
tabButton.className += ' fw-colour-picker-tab-button-active';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(options.showPresetsTab)
|
|
||||||
createTab('presets', 'Presets', function() {
|
|
||||||
var presets = options.presets;
|
|
||||||
var cont = document.createElement('div');
|
|
||||||
|
|
||||||
for(var i = 0; i < presets.length; ++i)
|
|
||||||
(function(preset) {
|
|
||||||
var option = document.createElement('a');
|
|
||||||
option.href = 'javascript:void(0);';
|
|
||||||
option.className = 'fw-colour-picker-presets-option';
|
|
||||||
option.style.background = hexFormat(preset.c);
|
|
||||||
option.title = preset.n;
|
|
||||||
option.onclick = function() {
|
|
||||||
setColour(preset.c);
|
|
||||||
};
|
|
||||||
onColourChange.push(function(value) {
|
|
||||||
option.classList[(value === preset.c ? 'add' : 'remove')]('fw-colour-picker-presets-option-active');
|
|
||||||
});
|
|
||||||
cont.appendChild(option);
|
|
||||||
})(presets[i]);
|
|
||||||
|
|
||||||
return cont;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(options.showGridTab)
|
|
||||||
createTab('grid', 'Grid', function() {
|
|
||||||
var greys = [0xFFFFFF, 0xEBEBEB, 0xD6D6D6, 0xC2C2C2, 0xADADAD, 0x999999, 0x858585, 0x707070, 0x5C5C5C, 0x474747, 0x333333, 0];
|
|
||||||
var colours = [0x00A1D8, 0x0061FE, 0x4D22B2, 0x982ABC, 0xB92D5D, 0xFF4015, 0xFF6A00, 0xFFAB01, 0xFDC700, 0xFEFB41, 0xD9EC37, 0x76BB40];
|
|
||||||
var shades = [-.675, -.499, -.345, -.134, 0, .134, .345, .499, .675];
|
|
||||||
|
|
||||||
var cont = document.createElement('div');
|
|
||||||
|
|
||||||
for(var i = 0; i < greys.length; ++i)
|
|
||||||
(function(grey) {
|
|
||||||
var option = document.createElement('a');
|
|
||||||
option.href = 'javascript:void(0);';
|
|
||||||
option.className = 'fw-colour-picker-grid-option';
|
|
||||||
option.style.background = hexFormat(grey);
|
|
||||||
option.onclick = function() {
|
|
||||||
setColour(grey);
|
|
||||||
};
|
|
||||||
onColourChange.push(function(value) {
|
|
||||||
option.classList[(value === grey ? 'add' : 'remove')]('fw-colour-picker-grid-option-active');
|
|
||||||
});
|
|
||||||
cont.appendChild(option);
|
|
||||||
})(greys[i]);
|
|
||||||
|
|
||||||
for(var i = 0; i < shades.length; ++i)
|
|
||||||
for(var j = 0; j < colours.length; ++j)
|
|
||||||
(function(colour) {
|
|
||||||
var option = document.createElement('a');
|
|
||||||
option.href = 'javascript:void(0);';
|
|
||||||
option.className = 'fw-colour-picker-grid-option';
|
|
||||||
option.style.background = hexFormat(colour);
|
|
||||||
option.onclick = function() {
|
|
||||||
setColour(colour);
|
|
||||||
};
|
|
||||||
onColourChange.push(function(value) {
|
|
||||||
option.classList[(value === colour ? 'add' : 'remove')]('fw-colour-picker-grid-option-active');
|
|
||||||
});
|
|
||||||
cont.appendChild(option);
|
|
||||||
})(shadeColour(colours[j], shades[i]));
|
|
||||||
|
|
||||||
return cont;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(options.showSlidersTab)
|
|
||||||
createTab('sliders', 'Sliders', function() {
|
|
||||||
var cont = document.createElement('div');
|
|
||||||
|
|
||||||
var addSlider = function(id, name, update, apply) {
|
|
||||||
var sCont = document.createElement('div');
|
|
||||||
sCont.className = 'fw-colour-picker-slider fw-colour-picker-slider-' + id;
|
|
||||||
cont.appendChild(sCont);
|
|
||||||
|
|
||||||
var sName = document.createElement('div');
|
|
||||||
sName.className = 'fw-colour-picker-slider-name';
|
|
||||||
sName.textContent = name;
|
|
||||||
sCont.appendChild(sName);
|
|
||||||
|
|
||||||
var sValue = document.createElement('div');
|
|
||||||
sValue.className = 'fw-colour-picker-slider-value';
|
|
||||||
sCont.appendChild(sValue);
|
|
||||||
|
|
||||||
var sValueSliderCont = document.createElement('div');
|
|
||||||
sValueSliderCont.className = 'fw-colour-picker-slider-value-slider-container';
|
|
||||||
sValue.appendChild(sValueSliderCont);
|
|
||||||
|
|
||||||
var sGradient = document.createElement('div');
|
|
||||||
sGradient.className = 'fw-colour-picker-slider-gradient';
|
|
||||||
sValueSliderCont.appendChild(sGradient);
|
|
||||||
|
|
||||||
var sValueSlider = document.createElement('input');
|
|
||||||
sValueSlider.type = 'range';
|
|
||||||
if(sValueSlider.type === 'range') {
|
|
||||||
sValueSlider.className = 'fw-colour-picker-slider-value-slider';
|
|
||||||
sValueSlider.min = '0';
|
|
||||||
sValueSlider.max = '255';
|
|
||||||
sValueSlider.onchange = function() {
|
|
||||||
setColour(apply(colour, sValueSlider.value));
|
|
||||||
};
|
|
||||||
sValueSliderCont.appendChild(sValueSlider);
|
|
||||||
} else
|
|
||||||
sValueSlider = undefined;
|
|
||||||
|
|
||||||
var sValueInputContainer = document.createElement('div');
|
|
||||||
sValueInputContainer.className = 'fw-colour-picker-slider-value-input-container';
|
|
||||||
sValue.appendChild(sValueInputContainer);
|
|
||||||
|
|
||||||
var sValueInput = document.createElement('input');
|
|
||||||
sValueInput.className = 'fw-colour-picker-slider-value-input';
|
|
||||||
sValueInput.type = 'number';
|
|
||||||
sValueInput.min = '0';
|
|
||||||
sValueInput.max = '255';
|
|
||||||
sValueInput.onchange = function() {
|
|
||||||
setColour(apply(colour, sValueInput.value));
|
|
||||||
};
|
|
||||||
sValueInputContainer.appendChild(sValueInput);
|
|
||||||
|
|
||||||
sGradient.onmousedown = function(ev) {
|
|
||||||
if(ev.button === 0)
|
|
||||||
setColour(apply(colour, Math.floor(255 * (Math.max(0, Math.min(200, (ev.layerX - 5))) / 200))));
|
|
||||||
};
|
|
||||||
|
|
||||||
onColourChange.push(function(colour) {
|
|
||||||
if(sValueSlider)
|
|
||||||
sValueSlider.value = update(colour);
|
|
||||||
sValueInput.value = update(colour);
|
|
||||||
|
|
||||||
var gradient = 'linear-gradient(to right, ' + hexFormat(apply(colour, 0)) + ', ' + hexFormat(apply(colour, 0xFF)) + ')';
|
|
||||||
sGradient.style.background = '';
|
|
||||||
sGradient.style.background = gradient;
|
|
||||||
if(!sGradient.style.background)
|
|
||||||
sGradient.style.background = '-moz-' + gradient;
|
|
||||||
if(!sGradient.style.background)
|
|
||||||
sGradient.style.background = '-webkit-' + gradient;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
addSlider('red', 'Red',
|
|
||||||
function(value) { return (value >> 16) & 0xFF; },
|
|
||||||
function(colour, value) { return (colour & 0xFFFF) | (Math.min(255, Math.max(0, value)) << 16); }
|
|
||||||
);
|
|
||||||
addSlider('green', 'Green',
|
|
||||||
function(value) { return (value >> 8) & 0xFF; },
|
|
||||||
function(colour, value) { return (colour & 0xFF00FF) | (Math.min(255, Math.max(0, value)) << 8); }
|
|
||||||
);
|
|
||||||
addSlider('blue', 'Blue',
|
|
||||||
function(value) { return value & 0xFF; },
|
|
||||||
function(colour, value) { return (colour & 0xFFFF00) | Math.min(255, Math.max(0, value)); }
|
|
||||||
);
|
|
||||||
|
|
||||||
return cont;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(activeTab) {
|
|
||||||
height += 261;
|
|
||||||
form.appendChild(tabbed);
|
|
||||||
}
|
|
||||||
|
|
||||||
var middleRow = document.createElement('div');
|
|
||||||
middleRow.className = 'fw-colour-picker-middle-row';
|
|
||||||
form.appendChild(middleRow);
|
|
||||||
|
|
||||||
var colourPreviewContainer = document.createElement('div');
|
|
||||||
colourPreviewContainer.className = 'fw-colour-picker-colour-preview-container';
|
|
||||||
middleRow.appendChild(colourPreviewContainer);
|
|
||||||
|
|
||||||
var colourPreview = document.createElement('div');
|
|
||||||
colourPreview.className = 'fw-colour-picker-colour-preview';
|
|
||||||
colourPreviewContainer.appendChild(colourPreview);
|
|
||||||
onColourChange.push(function(colour) {
|
|
||||||
colourPreview.style.background = hexFormat(colour);
|
|
||||||
});
|
|
||||||
|
|
||||||
var values = {};
|
|
||||||
var valuesContainer = document.createElement('div');
|
|
||||||
valuesContainer.className = 'fw-colour-picker-values-container';
|
|
||||||
middleRow.appendChild(valuesContainer);
|
|
||||||
|
|
||||||
var addValue = function(id, name, type, format, change) {
|
|
||||||
var valueContainer = document.createElement('label');
|
|
||||||
valueContainer.className = 'fw-colour-picker-values-child fw-colour-picker-' + id + '-value';
|
|
||||||
valuesContainer.appendChild(valueContainer);
|
|
||||||
|
|
||||||
var valueLabel = document.createElement('div');
|
|
||||||
valueLabel.textContent = name;
|
|
||||||
valueLabel.className = 'fw-colour-picker-values-child-label fw-colour-picker-' + id + '-value-label';
|
|
||||||
valueContainer.appendChild(valueLabel);
|
|
||||||
|
|
||||||
var valueInput = document.createElement('input');
|
|
||||||
valueInput.type = type;
|
|
||||||
valueInput.value = '0';
|
|
||||||
valueInput.className = 'fw-colour-picker-values-child-input fw-colour-picker-' + id + '-value-input';
|
|
||||||
valueInput.onchange = function() {
|
|
||||||
change(valueInput.value);
|
|
||||||
};
|
|
||||||
valueContainer.appendChild(valueInput);
|
|
||||||
|
|
||||||
onColourChange.push(function(colour) {
|
|
||||||
valueInput.value = format(colour);
|
|
||||||
});
|
|
||||||
|
|
||||||
values[id] = { c: valueContainer, l: valueLabel, i: valueInput };
|
|
||||||
};
|
|
||||||
|
|
||||||
if(options.showHexValue)
|
|
||||||
addValue('hex', 'Hex', 'text', function(value) {
|
|
||||||
return hexFormat(value);
|
|
||||||
}, function(value) {
|
|
||||||
while(value.substring(0, 1) === '#')
|
|
||||||
value = value.substring(1);
|
|
||||||
value = value.substring(0, 6);
|
|
||||||
|
|
||||||
if(value.length === 3)
|
|
||||||
value = value.substring(0, 1) + value.substring(0, 1)
|
|
||||||
+ value.substring(1, 2) + value.substring(1, 2)
|
|
||||||
+ value.substring(2, 3) + value.substring(2, 3);
|
|
||||||
|
|
||||||
if(value.length === 6)
|
|
||||||
setColour(parseInt(value, 16));
|
|
||||||
});
|
|
||||||
|
|
||||||
if(options.showRawValue)
|
|
||||||
addValue('raw', 'Raw', 'number', function(value) {
|
|
||||||
return value;
|
|
||||||
}, function(value) {
|
|
||||||
setColour(Math.min(0xFFFFFF, Math.max(0, parseInt(value))));
|
|
||||||
});
|
|
||||||
|
|
||||||
var buttons = {};
|
|
||||||
var buttonsContainer = document.createElement('div');
|
|
||||||
buttonsContainer.className = 'fw-colour-picker-buttons-container';
|
|
||||||
form.appendChild(buttonsContainer);
|
|
||||||
|
|
||||||
var buttonsContainerInner = document.createElement('div');
|
|
||||||
buttonsContainerInner.className = 'fw-colour-picker-buttons-container-inner';
|
|
||||||
buttonsContainer.appendChild(buttonsContainerInner);
|
|
||||||
|
|
||||||
var addButton = function(id, name, action) {
|
|
||||||
var button = document.createElement('input');
|
|
||||||
button.className = 'fw-colour-picker-buttons-button fw-colour-picker-buttons-' + id + '-button';
|
|
||||||
if(action === null) {
|
|
||||||
button.className += ' fw-colour-picker-buttons-button-submit';
|
|
||||||
onColourChange.push(function(colour, text) {
|
|
||||||
button.style.background = hexFormat(colour);
|
|
||||||
button.style.color = hexFormat(text);
|
|
||||||
});
|
|
||||||
button.type = 'submit';
|
|
||||||
} else {
|
|
||||||
button.onclick = function() { action(); };
|
|
||||||
button.type = 'button';
|
|
||||||
}
|
|
||||||
button.value = name;
|
|
||||||
buttonsContainerInner.appendChild(button);
|
|
||||||
buttons[id] = { b: button };
|
|
||||||
};
|
|
||||||
|
|
||||||
addButton('cancel', 'Cancel', cancel);
|
|
||||||
addButton('apply', 'Apply', null);
|
|
||||||
|
|
||||||
var setPosition = function(x, y) {
|
|
||||||
container.style.top = y >= 0 ? (y.toString() + 'px') : '';
|
|
||||||
container.style.left = x >= 0 ? (x.toString() + 'px') : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
setPosition(options.posX, options.posY);
|
|
||||||
runOnColourChange();
|
|
||||||
|
|
||||||
var appendTo = function(parent) {
|
|
||||||
parent.appendChild(container);
|
|
||||||
};
|
|
||||||
|
|
||||||
var pub = {
|
|
||||||
getWidth: function() { return 290; },
|
|
||||||
getHeight: function() { return height; },
|
|
||||||
getColour: function() { return colour; },
|
|
||||||
getContainer: function() { return container; },
|
|
||||||
setColour: setColour,
|
|
||||||
appendTo: appendTo,
|
|
||||||
setPosition: setPosition,
|
|
||||||
switchTab: switchTab,
|
|
||||||
close: close,
|
|
||||||
suggestPosition: function(mouseEvent) {
|
|
||||||
var x = 10, y = 10;
|
|
||||||
|
|
||||||
if(document.body.clientWidth > 340) {
|
|
||||||
x = mouseEvent.clientX;
|
|
||||||
y = mouseEvent.clientY;
|
|
||||||
|
|
||||||
var height = pub.getHeight(),
|
|
||||||
width = pub.getWidth();
|
|
||||||
|
|
||||||
if(y > height + 20)
|
|
||||||
y -= height;
|
|
||||||
if(x > document.body.clientWidth - width - 20)
|
|
||||||
x -= width;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
x: x,
|
|
||||||
y: y,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return pub;
|
|
||||||
};
|
|
||||||
FwColourPicker.hexFormat = function(raw) {
|
|
||||||
var str = raw.toString(16).substring(0, 6);
|
|
||||||
if(str.length < 6)
|
|
||||||
str = '000000'.substring(str.length) + str;
|
|
||||||
return '#' + str;
|
|
||||||
};
|
|
|
@ -1,12 +1,11 @@
|
||||||
.fw-colour-picker {
|
.colpick {
|
||||||
|
accent-color: var(--colpick-colour, #000);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 2px solid #123456;
|
border: 2px solid var(--colpick-colour, #000);
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
display: flex;
|
display: flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
background-color: #444;
|
background-color: #444;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 3px 10px #000;
|
box-shadow: 0 3px 10px #000;
|
||||||
|
@ -14,34 +13,30 @@
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
width: 290px;
|
width: 290px;
|
||||||
transition: width .2s, border-color .2s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.fw-colour-picker-form {
|
.colpick-form {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fw-colour-picker-tabbed {
|
.colpick-tabbed {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-tabbed-container {
|
.colpick-tabbed-container {
|
||||||
border: 2px solid #123456;
|
border: 2px solid var(--colpick-colour, #000);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
border-radius: 5px 5px 0 0;
|
border-radius: 5px 5px 0 0;
|
||||||
height: 234px;
|
height: 234px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
transition: border-color .2s;
|
|
||||||
}
|
}
|
||||||
.fw-colour-picker-tabbed-list {
|
.colpick-tabbed-list {
|
||||||
background-color: #222;
|
background-color: #222;
|
||||||
border-radius: 0 0 5px 5px;
|
border-radius: 0 0 5px 5px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fw-colour-picker-tab-button {
|
.colpick-tab-button {
|
||||||
background: #333;
|
background: #333;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
@ -50,92 +45,86 @@
|
||||||
padding: 3px 5px;
|
padding: 3px 5px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
margin-right: 1px;
|
margin-right: 1px;
|
||||||
transition: background .2s, border-color .2s;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-tab-button:hover {
|
.colpick-tab-button:hover {
|
||||||
background: #444;
|
background: #444;
|
||||||
border-color: #444;
|
border-color: #444;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-tab-button:focus {
|
.colpick-tab-button:focus {
|
||||||
border-color: #fff;
|
border-color: #fff;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-tab-button-active {
|
.colpick-tab-button-active {
|
||||||
background: #123456;
|
background: var(--colpick-colour, #000);
|
||||||
border-color: #123456;
|
border-color: var(--colpick-colour, #000);
|
||||||
color: #123456;
|
color: var(--colpick-text, #000);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fw-colour-picker-middle-row {
|
.colpick-middle-row {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fw-colour-picker-colour-preview-container {
|
.colpick-colour-preview-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-colour-preview {
|
.colpick-colour-preview {
|
||||||
display: block;
|
display: block;
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background: #123456;
|
background: var(--colpick-colour, #000);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fw-colour-picker-values-container {
|
.colpick-values-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fw-colour-picker-values-child {
|
.colpick-values-child {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 2px 3px;
|
padding: 2px 3px;
|
||||||
margin: 1px;
|
margin: 1px;
|
||||||
margin-left: 31px;
|
margin-left: 31px;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-values-child-label {
|
.colpick-values-child-label {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-values-child-input {
|
.colpick-values-child-input {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border: 1px solid #222;
|
border: 1px solid #222;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
background: #333;
|
background: #333;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding: 1px;
|
padding: 1px;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
transition: border-color .2s;
|
|
||||||
outline-style: none;
|
outline-style: none;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-values-child-input:focus {
|
.colpick-values-child-input:focus {
|
||||||
border-color: #777;
|
border-color: #777;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fw-colour-picker-buttons-container {
|
.colpick-buttons-container {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
margin: 1px;
|
margin: 1px;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-buttons-container-inner {
|
.colpick-buttons-container-inner {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fw-colour-picker-buttons-button {
|
.colpick-buttons-button {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background: #222;
|
background: #222;
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
|
@ -146,116 +135,107 @@
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-buttons-button:focus {
|
.colpick-buttons-button:focus {
|
||||||
box-shadow: 0 0 0 1px #000, inset 0 0 0 1px #fff;
|
box-shadow: 0 0 0 1px #000, inset 0 0 0 1px #fff;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-buttons-button-submit {
|
.colpick-buttons-button-submit {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #123456;
|
color: var(--colpick-text, #fff);
|
||||||
background: #123456;
|
background: var(--colpick-colour, #000);
|
||||||
transition: background .2s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.fw-colour-picker-tab-container {
|
.colpick-tab-container {}
|
||||||
display: none;
|
.colpick-tab-container-inactive {
|
||||||
|
display: none !important;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-tab-container-active {
|
|
||||||
|
.colpick-tab-presets-container {
|
||||||
|
padding: 2px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
.colpick-presets-option {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
|
||||||
|
|
||||||
.fw-colour-picker-tab-presets-container {
|
|
||||||
text-align: center;
|
|
||||||
padding-top: 3px;
|
|
||||||
padding-left: 3px;
|
|
||||||
}
|
|
||||||
.fw-colour-picker-presets-option {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
margin-right: 3px;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-presets-option:focus {
|
.colpick-presets-option:focus {
|
||||||
box-shadow: 0 0 0 1px #fff, 0 0 0 2px #000, inset 0 0 0 1px #000;
|
box-shadow: 0 0 0 1px #fff, 0 0 0 2px #000, inset 0 0 0 1px #000;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-presets-option-active {
|
.colpick-presets-option-active {
|
||||||
box-shadow: 0 0 0 1px #000, inset 0 0 0 1px #fff;
|
box-shadow: 0 0 0 1px #000, inset 0 0 0 1px #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fw-colour-picker-tab-grid-container {
|
.colpick-tab-grid-container {
|
||||||
text-align: center;
|
display: grid;
|
||||||
|
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
.fw-colour-picker-grid-option {
|
.colpick-grid-option {
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
width: 23px;
|
width: 23px;
|
||||||
height: 23px;
|
height: 23px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
position: relative;
|
|
||||||
cursor: cell;
|
cursor: cell;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-grid-option:focus {
|
.colpick-grid-option:focus {
|
||||||
box-shadow: 0 0 0 1px #fff, 0 0 0 2px #000, inset 0 0 0 1px #000;
|
box-shadow: 0 0 0 1px #fff, 0 0 0 2px #000, inset 0 0 0 1px #000;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-grid-option-active {
|
.colpick-grid-option-active {
|
||||||
box-shadow: 0 0 0 1px #000, inset 0 0 0 1px #fff;
|
box-shadow: 0 0 0 1px #000, inset 0 0 0 1px #fff;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fw-colour-picker-slider {
|
.colpick-slider {
|
||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-slider-gradient {
|
.colpick-slider-gradient {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-slider-name {
|
.colpick-slider-name {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-slider-value-slider-container {
|
.colpick-slider-value-slider-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
margin: 4px;
|
margin: 4px;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-slider-value-slider {
|
.colpick-slider-value-slider {
|
||||||
|
accent-color: var(--colpick-slider-colour, var(--colpick-colour, #000));
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-slider-value-input-container {
|
.colpick-slider-value-input-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 64px;
|
width: 64px;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-slider-value-input {
|
.colpick-slider-value-input {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border: 1px solid #222;
|
border: 1px solid #222;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
background: #333;
|
background: #333;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding: 1px;
|
padding: 1px;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
transition: border-color .2s;
|
|
||||||
outline-style: none;
|
outline-style: none;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-slider-value-input:focus {
|
.colpick-slider-value-input:focus {
|
||||||
border-color: #777;
|
border-color: #777;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-slider-red .fw-colour-picker-slider-value-input:focus {
|
.colpick-slider-red .colpick-slider-value-input:focus {
|
||||||
border-color: #f00;
|
border-color: #f00;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-slider-green .fw-colour-picker-slider-value-input:focus {
|
.colpick-slider-green .colpick-slider-value-input:focus {
|
||||||
border-color: #0f0;
|
border-color: #0f0;
|
||||||
}
|
}
|
||||||
.fw-colour-picker-slider-blue .fw-colour-picker-slider-value-input:focus {
|
.colpick-slider-blue .colpick-slider-value-input:focus {
|
||||||
border-color: #00f;
|
border-color: #00f;
|
||||||
}
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
@include __animations.css;
|
@include __animations.css;
|
||||||
@include _main.css;
|
@include _main.css;
|
||||||
|
|
||||||
@include views.css;
|
@include views.css;
|
||||||
|
|
||||||
@include chat.css;
|
@include chat.css;
|
||||||
@include domaintrans.css;
|
@include domaintrans.css;
|
||||||
@include eeprom.css;
|
@include eeprom.css;
|
||||||
|
@ -13,6 +15,9 @@
|
||||||
@include setting.css;
|
@include setting.css;
|
||||||
@include sidebar.css;
|
@include sidebar.css;
|
||||||
@include umi.css;
|
@include umi.css;
|
||||||
|
|
||||||
|
@include colpick.css;
|
||||||
|
|
||||||
@include zz_ls_archaic.css;
|
@include zz_ls_archaic.css;
|
||||||
@include zz_ls_blue.css;
|
@include zz_ls_blue.css;
|
||||||
@include zz_ls_dark.css;
|
@include zz_ls_dark.css;
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
<link rel="manifest" href="/manifest.json">
|
<link rel="manifest" href="/manifest.json">
|
||||||
<link href="/vendor/fontawesome/css/all.min.css" rel="stylesheet" type="text/css">
|
<link href="/vendor/fontawesome/css/all.min.css" rel="stylesheet" type="text/css">
|
||||||
<link href="{mami.css}" rel="stylesheet" type="text/css">
|
<link href="{mami.css}" rel="stylesheet" type="text/css">
|
||||||
<link href="/picker.css" rel="stylesheet" type="text/css">
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
|
@ -23,7 +22,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</noscript>
|
</noscript>
|
||||||
<script type="text/javascript" charset="utf-8" src="/picker.js"></script>
|
|
||||||
<script type="text/javascript" charset="utf-8" src="{mami-init.js}"></script>
|
<script type="text/javascript" charset="utf-8" src="{mami-init.js}"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,58 +1,13 @@
|
||||||
|
#include srle.js
|
||||||
#include utility.js
|
#include utility.js
|
||||||
#include audio/buffer.js
|
#include audio/buffer.js
|
||||||
#include audio/source.js
|
#include audio/source.js
|
||||||
|
|
||||||
const MamiSRLEEncode = function(input, cutoff) {
|
|
||||||
let output = '', last = '', repeat = 0;
|
|
||||||
|
|
||||||
input = (input || '').toString();
|
|
||||||
cutoff = cutoff || 1
|
|
||||||
|
|
||||||
for(let i = 0; i <= input.length; ++i) {
|
|
||||||
const chr = input[i];
|
|
||||||
if(last === chr)
|
|
||||||
++repeat;
|
|
||||||
else {
|
|
||||||
if(repeat > cutoff)
|
|
||||||
for(const repChr in repeat.toString()) output += ')!@#$%^&*('[parseInt(repChr)];
|
|
||||||
else
|
|
||||||
output += last.repeat(repeat);
|
|
||||||
repeat = 0;
|
|
||||||
if(chr !== undefined) {
|
|
||||||
output += chr;
|
|
||||||
last = chr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
};
|
|
||||||
|
|
||||||
const MamiSRLEDecode = function(input) {
|
|
||||||
let output = '', repeat = '', chr;
|
|
||||||
|
|
||||||
input = (input || '').toString().split('').reverse();
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
const chr = input.pop(), num = ')!@#$%^&*('.indexOf(chr);
|
|
||||||
if(num >= 0) repeat += num;
|
|
||||||
else {
|
|
||||||
if(repeat) {
|
|
||||||
output += output.slice(-1).repeat(parseInt(repeat));
|
|
||||||
repeat = '';
|
|
||||||
}
|
|
||||||
if(chr === undefined) break;
|
|
||||||
output += chr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
};
|
|
||||||
const MamiDetectAutoPlaySource = '/+NIxA!!FhpbmcA#PA$wA@fgAV$#q$#/$#A#OUxBTUUzLjEwMAIeA!)UCCQC8CIA@gA@H49wpKWgA!%&/+MYxA$NIA$ExBTUUzLjEwMFV^%/+MYxDsA@NIA$FV&&/+MYxHYA@NIA$FV&&';
|
const MamiDetectAutoPlaySource = '/+NIxA!!FhpbmcA#PA$wA@fgAV$#q$#/$#A#OUxBTUUzLjEwMAIeA!)UCCQC8CIA@gA@H49wpKWgA!%&/+MYxA$NIA$ExBTUUzLjEwMFV^%/+MYxDsA@NIA$FV&&/+MYxHYA@NIA$FV&&';
|
||||||
|
|
||||||
const MamiDetectAutoPlay = async () => {
|
const MamiDetectAutoPlay = async () => {
|
||||||
try {
|
try {
|
||||||
const audio = $e('audio', { src: 'data:audio/mpeg;base64,' + MamiSRLEDecode(MamiDetectAutoPlaySource) });
|
const audio = $e('audio', { src: 'data:audio/mpeg;base64,' + MamiSRLE.decode(MamiDetectAutoPlaySource) });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await audio.play();
|
await audio.play();
|
||||||
|
|
374
src/mami.js/colpick/picker.jsx
Normal file
374
src/mami.js/colpick/picker.jsx
Normal file
|
@ -0,0 +1,374 @@
|
||||||
|
const MamiColourPicker = function(callback, options, colour, onClose) {
|
||||||
|
if(typeof callback !== 'function')
|
||||||
|
return;
|
||||||
|
if(typeof options !== 'object')
|
||||||
|
options = {};
|
||||||
|
if(typeof colour !== 'number')
|
||||||
|
colour = parseInt(colour || 0);
|
||||||
|
|
||||||
|
const readThres = 168,
|
||||||
|
lumiRed = .299,
|
||||||
|
lumiGreen = .587,
|
||||||
|
lumiBlue = .114;
|
||||||
|
|
||||||
|
const hexFormat = raw => {
|
||||||
|
let str = raw.toString(16).substring(0, 6);
|
||||||
|
if(str.length < 6)
|
||||||
|
str = '000000'.substring(str.length) + str;
|
||||||
|
return `#${str}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const extractRGB = raw => [
|
||||||
|
(raw >> 16) & 0xFF,
|
||||||
|
(raw >> 8) & 0xFF,
|
||||||
|
raw & 0xFF,
|
||||||
|
];
|
||||||
|
|
||||||
|
const calcLumi = raw => {
|
||||||
|
const rgb = extractRGB(raw);
|
||||||
|
return rgb[0] * lumiRed
|
||||||
|
+ rgb[1] * lumiGreen
|
||||||
|
+ rgb[2] * lumiBlue;
|
||||||
|
};
|
||||||
|
|
||||||
|
const textColour = raw => calcLumi(raw) > readThres ? 0 : 0xFFFFFF;
|
||||||
|
|
||||||
|
const weightNum = (n1, n2, w) => {
|
||||||
|
w = Math.min(1, Math.max(0, w));
|
||||||
|
return Math.round((n1 * w) + (n2 * (1 - w)));
|
||||||
|
};
|
||||||
|
|
||||||
|
const weightColour = (c1, c2, w) => {
|
||||||
|
c1 = extractRGB(c1);
|
||||||
|
c2 = extractRGB(c2);
|
||||||
|
return (weightNum(c1[0], c2[0], w) << 16)
|
||||||
|
| (weightNum(c1[1], c2[1], w) << 8)
|
||||||
|
| weightNum(c1[2], c2[2], w);
|
||||||
|
};
|
||||||
|
|
||||||
|
const shadeColour = (raw, offset) => {
|
||||||
|
if(offset == 0)
|
||||||
|
return raw;
|
||||||
|
|
||||||
|
let dir = 0xFFFFFF;
|
||||||
|
if(offset < 0) {
|
||||||
|
dir = 0;
|
||||||
|
offset *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return weightColour(dir, raw, offset);
|
||||||
|
};
|
||||||
|
|
||||||
|
const verifyOption = (name, type, def) => {
|
||||||
|
if(typeof options[name] !== type)
|
||||||
|
options[name] = def;
|
||||||
|
};
|
||||||
|
|
||||||
|
verifyOption('posX', 'number', -1);
|
||||||
|
verifyOption('posY', 'number', -1);
|
||||||
|
verifyOption('presets', 'object', []);
|
||||||
|
verifyOption('showPresetsTab', 'boolean', options.presets.length > 0);
|
||||||
|
verifyOption('showGridTab', 'boolean', true);
|
||||||
|
verifyOption('showSlidersTab', 'boolean', true);
|
||||||
|
verifyOption('showHexValue', 'boolean', true);
|
||||||
|
verifyOption('showRawValue', 'boolean', true);
|
||||||
|
verifyOption('autoClose', 'boolean', true);
|
||||||
|
|
||||||
|
const onColourChange = [];
|
||||||
|
const runOnColourChange = () => {
|
||||||
|
const text = textColour(colour);
|
||||||
|
for(const handler of onColourChange)
|
||||||
|
handler(colour, text);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setColour = raw => {
|
||||||
|
colour = parseInt(raw || 0) & 0xFFFFFF;
|
||||||
|
runOnColourChange();
|
||||||
|
};
|
||||||
|
|
||||||
|
const runCallback = apply => {
|
||||||
|
const result = Object.defineProperties({}, {
|
||||||
|
apply: { value: apply },
|
||||||
|
colour: { value: colour },
|
||||||
|
hex: { get() { return hexFormat(colour); } },
|
||||||
|
});
|
||||||
|
|
||||||
|
callback(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
const apply = () => {
|
||||||
|
runCallback(true);
|
||||||
|
if(options.autoClose)
|
||||||
|
close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const cancel = () => {
|
||||||
|
runCallback(false);
|
||||||
|
if(options.autoClose)
|
||||||
|
close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
if(onClose && onClose())
|
||||||
|
return;
|
||||||
|
container.parentNode.removeChild(container);
|
||||||
|
};
|
||||||
|
|
||||||
|
let height = 96;
|
||||||
|
|
||||||
|
const container = <div class="colpick" style={{ zIndex: '9001' }}/>;
|
||||||
|
onColourChange.push((colour, text) => {
|
||||||
|
container.style.setProperty('--colpick-colour', hexFormat(colour));
|
||||||
|
container.style.setProperty('--colpick-text', hexFormat(text));
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = <form class="colpick-form" onsubmit={ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
apply();
|
||||||
|
return false;
|
||||||
|
}} />;
|
||||||
|
container.appendChild(form);
|
||||||
|
|
||||||
|
const tabs = {};
|
||||||
|
let activeTab = undefined;
|
||||||
|
|
||||||
|
let tabbedContainer, tabbedList;
|
||||||
|
const tabbed = <div class="colpick-tabbed">
|
||||||
|
{tabbedContainer = <div class="colpick-tabbed-container"/>}
|
||||||
|
{tabbedList = <div class="colpick-tabbed-list"/>}
|
||||||
|
</div>;
|
||||||
|
|
||||||
|
const switchTab = (id) => {
|
||||||
|
if(activeTab == tabs[id])
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(activeTab) {
|
||||||
|
activeTab.c.classList.toggle('colpick-tab-container-inactive', true);
|
||||||
|
activeTab.b.classList.toggle('colpick-tab-button-active', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
activeTab = tabs[id] || undefined;
|
||||||
|
|
||||||
|
if(activeTab) {
|
||||||
|
activeTab.c.classList.toggle('colpick-tab-container-inactive', false);
|
||||||
|
activeTab.b.classList.toggle('colpick-tab-button-active', true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createTab = (id, name, construct) => {
|
||||||
|
const tabContainer = construct();
|
||||||
|
tabContainer.className = `colpick-tab-container colpick-tab-${id}-container colpick-tab-container-inactive`;
|
||||||
|
tabbedContainer.appendChild(tabContainer);
|
||||||
|
|
||||||
|
const tabButton = <input type="button" value={name} class={['colpick-tab-button', `colpick-tab-${id}-button`]} onclick={() => switchTab(id)}/>;
|
||||||
|
tabbedList.appendChild(tabButton);
|
||||||
|
|
||||||
|
tabs[id] = { c: tabContainer, b: tabButton };
|
||||||
|
|
||||||
|
if(activeTab === undefined) {
|
||||||
|
activeTab = tabs[id];
|
||||||
|
tabContainer.classList.remove('colpick-tab-container-inactive');
|
||||||
|
tabButton.classList.add('colpick-tab-button-active');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(options.showPresetsTab)
|
||||||
|
createTab('presets', 'Presets', () => {
|
||||||
|
const presets = options.presets;
|
||||||
|
const cont = <div/>;
|
||||||
|
|
||||||
|
for(const preset of presets) {
|
||||||
|
const option = <a href="javascript:void(0);" class="colpick-presets-option" style={{ background: hexFormat(preset.c) }} title={preset.n} onclick={() => setColour(preset.c)}/>;
|
||||||
|
onColourChange.push(value => option.classList.toggle('colpick-presets-option-active', value === preset.c));
|
||||||
|
cont.appendChild(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cont;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(options.showGridTab)
|
||||||
|
createTab('grid', 'Grid', () => {
|
||||||
|
const greys = [0xFFFFFF, 0xEBEBEB, 0xD6D6D6, 0xC2C2C2, 0xADADAD, 0x999999, 0x858585, 0x707070, 0x5C5C5C, 0x474747, 0x333333, 0];
|
||||||
|
const colours = [0x00A1D8, 0x0061FE, 0x4D22B2, 0x982ABC, 0xB92D5D, 0xFF4015, 0xFF6A00, 0xFFAB01, 0xFDC700, 0xFEFB41, 0xD9EC37, 0x76BB40];
|
||||||
|
const shades = [-.675, -.499, -.345, -.134, 0, .134, .345, .499, .675];
|
||||||
|
|
||||||
|
const cont = <div/>;
|
||||||
|
|
||||||
|
for(const grey of greys) {
|
||||||
|
const option = <a href="javascript:void(0);" class="colpick-grid-option" style={{ background: hexFormat(grey) }} onclick={() => setColour(grey)}/>;
|
||||||
|
onColourChange.push(value => option.classList.toggle('colpick-grid-option-active', value === grey));
|
||||||
|
cont.appendChild(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const shade of shades)
|
||||||
|
for(const colour of colours) {
|
||||||
|
const shaded = shadeColour(colour, shade);
|
||||||
|
const option = <a href="javascript:void(0);" class="colpick-grid-option" style={{ background: hexFormat(shaded) }} onclick={() => setColour(shaded)}/>;
|
||||||
|
onColourChange.push(value => option.classList.toggle('colpick-grid-option-active', value === shaded));
|
||||||
|
cont.appendChild(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cont;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(options.showSlidersTab)
|
||||||
|
createTab('sliders', 'Sliders', () => {
|
||||||
|
const cont = <div/>;
|
||||||
|
|
||||||
|
const addSlider = (id, name, update, apply) => {
|
||||||
|
let sGradient, sValueSlider, sValueInput;
|
||||||
|
|
||||||
|
const sCont = <div class={['colpick-slider', `colpick-slider-${id}`]}>
|
||||||
|
<div class="colpick-slider-name">{name}</div>
|
||||||
|
<div class="colpick-slider-value">
|
||||||
|
<div class="colpick-slider-value-slider-container">
|
||||||
|
{sGradient = <div class="colpick-slider-gradient" onmousedown={ev => { if(ev.button === 0) setColour(apply(colour, Math.floor(255 * (Math.max(0, Math.min(200, (ev.layerX - 5))) / 200)))) }}/>}
|
||||||
|
{sValueSlider = <input class="colpick-slider-value-slider" type="range" min="0" max="255" oninput={() => setColour(apply(colour, sValueSlider.value))}/>}
|
||||||
|
</div>
|
||||||
|
<div class="colpick-slider-value-input-container">
|
||||||
|
{sValueInput = <input class="colpick-slider-value-input" type="number" min="0" max="255" oninput={() => setColour(apply(colour, sValueInput.value))}/>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
cont.appendChild(sCont);
|
||||||
|
|
||||||
|
onColourChange.push(colour => {
|
||||||
|
sCont.style.setProperty('--colpick-slider-colour', hexFormat(apply(0, update(colour))));
|
||||||
|
sValueSlider.value = update(colour);
|
||||||
|
sValueInput.value = update(colour);
|
||||||
|
sGradient.style.background = `linear-gradient(to right, ${hexFormat(apply(colour, 0))}, ${hexFormat(apply(colour, 0xFF))})`;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
addSlider('red', 'Red',
|
||||||
|
value => (value >> 16) & 0xFF,
|
||||||
|
(colour, value) => (colour & 0xFFFF) | (Math.min(255, Math.max(0, value)) << 16)
|
||||||
|
);
|
||||||
|
addSlider('green', 'Green',
|
||||||
|
value => (value >> 8) & 0xFF,
|
||||||
|
(colour, value) => (colour & 0xFF00FF) | (Math.min(255, Math.max(0, value)) << 8)
|
||||||
|
);
|
||||||
|
addSlider('blue', 'Blue',
|
||||||
|
value => value & 0xFF,
|
||||||
|
(colour, value) => (colour & 0xFFFF00) | Math.min(255, Math.max(0, value))
|
||||||
|
);
|
||||||
|
|
||||||
|
return cont;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(activeTab) {
|
||||||
|
height += 261;
|
||||||
|
form.appendChild(tabbed);
|
||||||
|
}
|
||||||
|
|
||||||
|
const values = {};
|
||||||
|
let valuesContainer;
|
||||||
|
const middleRow = <div class="colpick-middle-row">
|
||||||
|
<div class="colpick-colour-preview-container">
|
||||||
|
<div class="colpick-colour-preview"/>
|
||||||
|
</div>
|
||||||
|
{valuesContainer = <div class="colpick-values-container"/>}
|
||||||
|
</div>;
|
||||||
|
form.appendChild(middleRow);
|
||||||
|
|
||||||
|
const addValue = (id, name, type, format, change) => {
|
||||||
|
let valueLabel, valueInput;
|
||||||
|
const valueContainer = <label class={['colpick-values-child', `colpick-${id}-value`]}>
|
||||||
|
{valueLabel = <div class={['colpick-values-child-label', `colpick-${id}-value-label`]}>{name}</div>}
|
||||||
|
{valueInput = <input class={['colpick-values-child-input', `colpick-${id}-value-input`]} type={type} value="0" onchange={() => change(valueInput.value)}/>}
|
||||||
|
</label>;
|
||||||
|
valuesContainer.appendChild(valueContainer);
|
||||||
|
|
||||||
|
onColourChange.push(colour => valueInput.value = format(colour));
|
||||||
|
|
||||||
|
values[id] = { c: valueContainer, l: valueLabel, i: valueInput };
|
||||||
|
};
|
||||||
|
|
||||||
|
if(options.showHexValue)
|
||||||
|
addValue('hex', 'Hex', 'text', value => hexFormat(value), value => {
|
||||||
|
while(value.substring(0, 1) === '#')
|
||||||
|
value = value.substring(1);
|
||||||
|
value = value.substring(0, 6);
|
||||||
|
|
||||||
|
if(value.length === 3)
|
||||||
|
value = value.substring(0, 1) + value.substring(0, 1)
|
||||||
|
+ value.substring(1, 2) + value.substring(1, 2)
|
||||||
|
+ value.substring(2, 3) + value.substring(2, 3);
|
||||||
|
|
||||||
|
if(value.length === 6)
|
||||||
|
setColour(parseInt(value, 16));
|
||||||
|
});
|
||||||
|
|
||||||
|
if(options.showRawValue)
|
||||||
|
addValue('raw', 'Raw', 'number', value => value, value => setColour(Math.min(0xFFFFFF, Math.max(0, parseInt(value)))));
|
||||||
|
|
||||||
|
let buttonsContainerInner;
|
||||||
|
const buttons = {};
|
||||||
|
const buttonsContainer = <div class="colpick-buttons-container">
|
||||||
|
{buttonsContainerInner = <div class="colpick-buttons-container-inner"/>}
|
||||||
|
</div>;
|
||||||
|
form.appendChild(buttonsContainer);
|
||||||
|
|
||||||
|
const addButton = (id, name, action) => {
|
||||||
|
const button = <input class={['colpick-buttons-button', `colpick-buttons-${id}-button`]} value={name}/>;
|
||||||
|
|
||||||
|
if(action === null) {
|
||||||
|
button.classList.add('colpick-buttons-button-submit');
|
||||||
|
button.type = 'submit';
|
||||||
|
} else {
|
||||||
|
button.onclick = () => action();
|
||||||
|
button.type = 'button';
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonsContainerInner.appendChild(button);
|
||||||
|
buttons[id] = { b: button };
|
||||||
|
};
|
||||||
|
|
||||||
|
addButton('cancel', 'Cancel', cancel);
|
||||||
|
addButton('apply', 'Apply', null);
|
||||||
|
|
||||||
|
const setPosition = (x, y) => {
|
||||||
|
container.style.top = y >= 0 ? `${y}px` : '';
|
||||||
|
container.style.left = x >= 0 ? `${x}px` : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
setPosition(options.posX, options.posY);
|
||||||
|
runOnColourChange();
|
||||||
|
|
||||||
|
const appendTo = parent => parent.appendChild(container);
|
||||||
|
|
||||||
|
const pub = {
|
||||||
|
getWidth: () => 290,
|
||||||
|
getHeight: () => height,
|
||||||
|
getColour: () => colour,
|
||||||
|
getContainer: () => container,
|
||||||
|
setColour: setColour,
|
||||||
|
appendTo: appendTo,
|
||||||
|
setPosition: setPosition,
|
||||||
|
switchTab: switchTab,
|
||||||
|
close: close,
|
||||||
|
suggestPosition: mouseEvent => {
|
||||||
|
let x = 10, y = 10;
|
||||||
|
|
||||||
|
if(document.body.clientWidth > 340) {
|
||||||
|
x = mouseEvent.clientX;
|
||||||
|
y = mouseEvent.clientY;
|
||||||
|
|
||||||
|
let height = pub.getHeight(),
|
||||||
|
width = pub.getWidth();
|
||||||
|
|
||||||
|
if(y > height + 20)
|
||||||
|
y -= height;
|
||||||
|
if(x > document.body.clientWidth - width - 20)
|
||||||
|
x -= width;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return pub;
|
||||||
|
};
|
63
src/mami.js/srle.js
Normal file
63
src/mami.js/srle.js
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
const MamiSRLE = (() => {
|
||||||
|
return {
|
||||||
|
encode: (input, cutoff) => {
|
||||||
|
let output = '',
|
||||||
|
last = '',
|
||||||
|
repeat = 0;
|
||||||
|
|
||||||
|
input = (input || '').toString();
|
||||||
|
cutoff = cutoff || 1
|
||||||
|
|
||||||
|
for(let i = 0; i <= input.length; ++i) {
|
||||||
|
const chr = input[i];
|
||||||
|
|
||||||
|
if(last === chr)
|
||||||
|
++repeat;
|
||||||
|
else {
|
||||||
|
if(repeat > cutoff)
|
||||||
|
for(const repChr in repeat.toString())
|
||||||
|
output += ')!@#$%^&*('[parseInt(repChr)];
|
||||||
|
else
|
||||||
|
output += last.repeat(repeat);
|
||||||
|
|
||||||
|
repeat = 0;
|
||||||
|
|
||||||
|
if(chr !== undefined) {
|
||||||
|
output += chr;
|
||||||
|
last = chr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode: input => {
|
||||||
|
let output = '',
|
||||||
|
repeat = '',
|
||||||
|
chr;
|
||||||
|
|
||||||
|
input = (input || '').toString().split('').reverse();
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
const chr = input.pop(), num = ')!@#$%^&*('.indexOf(chr);
|
||||||
|
|
||||||
|
if(num >= 0)
|
||||||
|
repeat += num;
|
||||||
|
else {
|
||||||
|
if(repeat) {
|
||||||
|
output += output.slice(-1).repeat(parseInt(repeat));
|
||||||
|
repeat = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chr === undefined)
|
||||||
|
break;
|
||||||
|
|
||||||
|
output += chr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
})();
|
|
@ -1,5 +1,6 @@
|
||||||
#include common.js
|
#include common.js
|
||||||
#include utility.js
|
#include utility.js
|
||||||
|
#include colpick/picker.jsx
|
||||||
#include ui/elems.js
|
#include ui/elems.js
|
||||||
#include ui/input-menus.js
|
#include ui/input-menus.js
|
||||||
#include ui/markup.js
|
#include ui/markup.js
|
||||||
|
@ -21,13 +22,10 @@ Umi.UI.Markup = (function() {
|
||||||
const elem = this;
|
const elem = this;
|
||||||
elem.dataset.umiPickerVisible = 'yes';
|
elem.dataset.umiPickerVisible = 'yes';
|
||||||
|
|
||||||
const picker = new FwColourPicker(
|
const picker = new MamiColourPicker(
|
||||||
function(picker, result) {
|
function(result) {
|
||||||
if(result !== null)
|
if(result.apply)
|
||||||
insertRaw(
|
insertRaw(`[color=${result.hex}]`, '[/color]');
|
||||||
'[color=' + FwColourPicker.hexFormat(result) + ']',
|
|
||||||
'[/color]'
|
|
||||||
);
|
|
||||||
}, { presets: futami.get('colours') }, null, function() {
|
}, { presets: futami.get('colours') }, null, function() {
|
||||||
elem.dataset.umiPickerVisible = 'no';
|
elem.dataset.umiPickerVisible = 'no';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue