MFColorPickerBasic / 1.0 / js / mf-colorpicker.js
file last updated : 2024-03-02
/*! methodfish package release

 Project      : MFColorPicker
 Release      : 1.0
 Release date : 2024-03-02 18:07:53
 License      : MIT
 For more information please refer to https://methodfish.com/Projects/MFColorPicker

*/


/*
 Improved color selector; implement by including the js and then using the following html you get the
 standard html color picker, but this will also maintain the list of default colors and store them in
 a named element so that this can be re-used if desired.
 To assist in the UX, this class will also add a tick button to the right of the standard input (I find
 it wrong that the "Other" color selector doesn't have a OK button. Note, it would be good to add a cross,
 but this is not possible as the selector is a modal popup.
 The selector also maintains the list of colors including the latest color at the front of the list

 This class requires material-icons to have the tick work.

     <link rel="stylesheet preload prefetch" as="style" href="https://fonts.googleapis.com/icon?family=Material+Icons">

     <input type="hidden" id="mfpresets" value="ffffff,000000,ff0000,00f000,0000ff">
     <input type="color" class="mfcolor" onchange="alert()">

     <script>
         const _mfcolorpicker = new MFColorPicker();
         _mfcolorpicker.init('mfpresets');
     </script>

 */

function MFColorPicker() {

    var _csvPresetElemId;
    //--------------------------------------
    function getMfDefaultColList(presetId) {
        if ( presetId ) {
            let el = document.querySelector('#' + presetId);
            if (el) return el.value;
        }
        return 'ffffff,000000,ababab,d7d7d7,d7d7d7,e6dee0,c00000,ea0000,ff0505,ff5001,ed7d31,375623,548235,00b050,a9d18e,e2f0d9';
    }

    //--------------------------------------
    function initMfColorButton(elem, presetId, tickclass, ticklabel) {

        elem.addEventListener('focusin', function() {
            elem.nextElementSibling.style.display='';
            elem.setAttribute('data-value0', elem.value);
        });


        elem.addEventListener('focusout', function() {
            elem.nextElementSibling.style.display='none';
        });


        elem.addEventListener('change', function() {
            elem.blur(); // force the focus away from elem so that the tick can return if the elem is tried again
            elem.nextElementSibling.style.display='none';

            mfSaveColor(elem);
        });


        if ( presetId ) elem.setAttribute('list', presetId);

        // Add a dummy tick to assist the UI
        var tick       = document.createElement('span');
        tick.className = tickclass+' mfcolorpicker-button';
        tick.innerHTML     = ticklabel;
        tick.style.cursor  = 'pointer';
        tick.style.fontSize = '120%';
        tick.style.display  = 'none';
        elem.parentNode.insertBefore(tick, elem.nextElementSibling);

    }

    //---------------------------------------
    function mfSaveColor(elem) {
        var listElem = document.querySelector('#'+_csvPresetElemId);
        
        // Add the new colour to the csv list
        if (listElem) {
            var csv  = listElem.value;
            var vals  = csv.split(',');
            var col = elem.value.replace(/#/,'');
            if (!vals.includes(col)) {
                if (elem.value != '') {
                    listElem.value = col + ',' + csv;

                    // Rebuild the list options set of colours
                    doBuildListElem();
                }
            }
        }
    }
    //---------------------------------------
    function doBuildListElem() {
        var list = document.querySelector('#'+_csvPresetElemId+'list');
        if (!list) {
            list    = document.createElement('datalist');
            list.id = _csvPresetElemId+'list';
            document.body.appendChild(list);
        }

        var cols = getMfDefaultColList(_csvPresetElemId).split(',');
        list.innerHTML='';
        for (var c = 0; c < cols.length; c++) {
            list.innerHTML += '<option>#' + cols[c].toUpperCase() + '</option>';
        } 
    }
    //---------------------------------------
    function hasClassName(elem, classNm) {
        const regex = new RegExp('\\b' + classNm + '\\b');
        return regex.test(elem.classList);
    }
    //---------------------------------------
    return {
        init(csvPresetElemId, tickclass, ticklabel) {

            if ( tickclass==undefined ) tickclass='material-icons';
            if ( ticklabel==undefined ) ticklabel='done';

            _csvPresetElemId = csvPresetElemId;
            doBuildListElem();

            var inputs = document.querySelectorAll('.mfcolorpicker');
            for (var i = 0; i < inputs.length; i++) {
                if ( !hasClassName(inputs[i], 'mfcolorpicker-ready')) {
                    inputs[i].className+=' mfcolorpicker-ready';
                    initMfColorButton(inputs[i], csvPresetElemId + 'list', tickclass, ticklabel);
                }
            }

        }
    }
}

About

License

Latest Release

Version 1.02024-05-08