bgrins / spectrum

The No Hassle JavaScript Colorpicker
https://bgrins.github.io/spectrum/
MIT License
2.32k stars 588 forks source link

Bespoke palette titles based on hex colors #407

Closed mjemerson closed 8 years ago

mjemerson commented 8 years ago

Hi,

I'm pretty new to Spectrum, and it's great - but there's something I would like to be able to do and I'm not sure if it's (easily) possible. I'm using the preferredFormat: "name" in the settings with a bunch of particular palette hex colours specified by the customer, but each colour has its own bespoke name. For example, fcf164 is "Primrose" and fdfdfd is "White" - so the hex codes do not match directly with an HTML colour name. Basically, what I'm asking is, is there a way of adding a bespoke palette title to the colour picker? I've tried using a jQuery $.each loop but because the colour palettes are generated on the fly in my project (based on a drag and drop method using clone) it doesn't work as it's not on document load.

Any help appreciated - sorry if my question is a bit vague though, I'm not great at explaining!

bgrins commented 8 years ago

Where do you want the new names to show up in the UI? And, does the picker have a text input field that needs to accept these names a valid input (and translate them to their associated hex value)?

mjemerson commented 8 years ago

Hi,

I'd like them to appear as the title tooltip, when you hover over them. So, for example, the hex is #028a92 and the name I'd like to appear in the floating tooltip is "Aqua Green" rather than the hex colour.

Currently, the picker code I have is as follows, which is attached to an input field on the right side of a div element:

$(".color-picker").spectrum({
    showPaletteOnly: true,
    palette: [["#fdfdfd", "#ffe5b0", "#fcf164", "#fdee43", "#fdcb37", "#fe6c14", "#ff4f27", "#ff4e31", "#fe4726", "#f52f1f", "#6f1c14", "#ff6e8e", "#e12768", "#392215", "#028a92", "#6ebd43", "#00870c",
        "#142c0f", "#a9daf0", "#12abdf", "#028fce", "#146aa8", "#115390", "#1f4592", "#254491", "#272c6d", "#8b8d83", "#6f7065", "#222222", "#bfbeb7", "#dba664" ]],
    move: updateContainer,
    change: updateContainer,
    preferredFormat: "name"
});

Where updateContainer basically changes the background colour of the element the picker is on to the picked colour.

mjemerson commented 8 years ago

If it helps, you can go to: http://dragdrop.stackastore.com.dev.media-orb.co.uk/ and then drag the boxes at the bottom onto the canvas - the picker appears as a small brush in the right corner, and you'll see that if you hover over the palette colours, it displays the hex code where I'd like it to display the bespoke colour name.

bgrins commented 8 years ago

Two options I can think of.. if you hook into the 'show' event and then get something like this: $(".color-picker").spectrum("container").find(".sp-palette span") to and then change the [title] attribute from your own code (it's set here: https://github.com/bgrins/spectrum/blob/master/spectrum.js#L143).

Another thing that might work is to modify TinyColor slightly so that it only ever accesses tinycolor.names in it's code base and then you could add/remove/modify the tinycolor.names object from your code (https://github.com/bgrins/TinyColor/blob/05b205826e2497022876b69d3327751c4a72b1ad/tinycolor.js#L793). Would also need to drop the hexNames variable in there and loop through tinycolor.names in toName. That might get tricky for you anyway if you need to dynamically change the color set or reset it to a starting point, so I'd see if the first option works out before trying that.

mjemerson commented 8 years ago

All right, thanks for that - I'll have a go and get back to you if I get problems.

mjemerson commented 8 years ago

Ah, the first option works great - I'd already written the logic to replace the RGB codes to the actual colour names so I just placed that in the spectrum.js code and it's working great, thank you!

bgrins commented 8 years ago

Cool, you're welcome

TheScendant commented 7 years ago

I was able to get this to work by hooking into the "show.spectrum" event:

let spec = $(item).spectrum({
  palette: [0,1,2],
  appendTo: "parent"
});

spec.on("show.spectrum", (e) => {
   console.warn($(document).find(".sp-thumb-el").length);
});
Thomas-Netset commented 1 year ago

Thanks, TheScendant! That helped me figure out what I had to do as I'm not very good with JavaScript at all.

However, I found that changes done in functions hooked on the "show.spectrum" event are overridden when you select a colour in the palette, so I hooked the function on the "change" event as well.

let replaceTitles = function(event) {
    let map = JSON.parse(HEX_TO_NAME_JSON);
    $(document).find('.sp-thumb-el').each(function() {
        let thumbEl = $(this);
        let newTitle = map[thumbEl.attr('title')];
        if (newTitle) {
            thumbEl.attr('title',newTitle);
        }
    });
};
spec.on('show.spectrum', replaceTitles);
spec.on('change', replaceTitles);

I would really prefer if a map of colour names could be supplied directly in Spectrum's constructor instead of having to hook onto events. Doing it this way seems really inefficient.

EDIT: Instead of hooking on to the 'change' event, I put "hideAfterPaletteSelect: true" in the constructor. But I did have to hook the function on the 'reflow.spectrum' event in order for the colour names to stay when clicking the "more" or "less" buttons. I also had to hook on to the event 'dragstop.spectrum', because otherwise the colour names disappeared when selecting a colour in the hue slider and colour picker area. I further found that entering a hexcode manually in the field under the colour picker area also removed the colour names, so I had to hook back onto the 'change' event to fix that.

This is highly inefficient. I have to hook onto four events and replace all colour titles every time. It would be much smoother if we could just provide a colour name map in the constructor or another function.