Change background color of multiple div containers with multiple jQuery-minicolors swatches

235 Views Asked by At

I am trying to use rails jquery minicolors to change the color of div containers. Each container is a box with a background-color attribute. My approach doesn't seem to be working out the way that I want. I am using the rails version of minicolors, but I still have to call minicolors through the js function. Anyhow, the swatches work without issue, but the boxes won't change color no matter what I do. How can I use each swatch to directly change the color of targeted div containers?

jsfiddle

https://jsfiddle.net/41zomar7/

gem

# Gemfile
gem 'jquery-minicolors-rails'

JS

var self = this;
$('#profile_color_attributes_border_background_color, #profile_color_attributes_body_background_color, #profile_color_attributes_header_label_background_color, #profile_color_attributes_information_box_color, #profile_color_attributes_about_me_background_box_color, #profile_color_attributes_browser_fill_color').minicolors({
    theme: 'bootstrap',
    animationSpeed: 50,
    animationEasing: 'swing',
    change: function (hex, opacity) {
        var color = $(this).minicolors('rgbaString');
        var parent = $(self).closest('div');
        if (parent.hasClass("profile-border-bg-color")) {
            $("preview-border").css("background-color", color);
        } else if (parent.hasClass("profile-body-bg-color")) {
            $("preview-container").css("background-color", color);
        } else if (parent.hasClass("profile-header-label-bg-color")) {
            $("preview-header-block").css("background-color", color);
        } else if (parent.hasClass("profile-info-color")) {
            $("preview-info-block").css("background-color", color);
        } else if (parent.hasClass("profile-about-me-color")) {
            $("preview-container-about-me").css("background-color", color);
        }
    }
});

_form.html.erb

<div class="col-md-3">
  <%= f.simple_fields_for :profile_color do |c| %>
    <label>Browser Fill Color</label>
    <%= c.input :browser_fill_color, as: :minicolors, class: 'form-control browser-fill-color', label: false %>
    <label>Avatar Background Color</label>
    <%= c.input :border_background_color, as: :minicolors, class: 'form-control profile-border-bg-color', label: false %>
    <label>Body Background Color</label>
    <%= c.input :body_background_color, as: :minicolors, class: 'form-control profile-body-bg-color', label: false %>
    <label>Header Label Background Color</label>
    <%= c.input :header_label_background_color, as: :minicolors, class: 'form-control profile-header-label-bg-color', label: false %>
    <label>Information Box Color</label>
    <%= c.input :information_box_color, as: :minicolors, class: 'form-control profile-info-color', label: false %>
    <label>About Me Background Color</label>
    <%= c.input :about_me_background_box_color, as: :minicolors, class: 'form-control profile-about-me-color', label: false %>
  <% end %>
</div>

<div class="col-md-4">
<div class="preview-container">
<div class=”browser-fill”>
    <div class="preview-header">
      <h6>Profile Color Preview</h6>
    </div>
    <div class="preview-border">
      <div class="preview-container-avatar">

      </div>
    </div>
    <div class="preview-container-about-me">

    </div>
    <div class="preview-header-block">

    </div>
    <div class="preview-info-block">

    </div>
   </div>
  </div>
</div>
1

There are 1 best solutions below

0
arieljuod On

Your parent assignment is wrong. The actual input element is the one with the classes you are testing the if/else chain. The parent div of each input (and the same for all of them) is that <div class="col-md-3"> wrapping the form tag.

Change your callback to:

    var color = $(this).minicolors('rgbaString');
    if ($(this).hasClass("profile-border-bg-color")) {
        $("preview-border").css("background-color", color);
    } else if ($(this).hasClass("profile-body-bg-color")) {
        $("preview-container").css("background-color", color);
    } else if ($(this).hasClass("profile-header-label-bg-color")) {
        $("preview-header-block").css("background-color", color);
    } else if ($(this).hasClass("profile-info-color")) {
        $("preview-info-block").css("background-color", color);
    } else if ($(this).hasClass("profile-about-me-color")) {
        $("preview-container-about-me").css("background-color", color);
    }

and you are done.


Just as suggestion, I'd recommend you to use data attributes instead of custom weird class names for what you are doing unless you are using those CSS classes for styling too. Something like:

<label>Avatar Background Color</label>
<%= c.input :border_background_color, as: :minicolors, class: 'form-control', data: {target: 'preview-border'}, label: false %>
<label>Body Background Color</label>
<%= c.input :body_background_color, as: :minicolors, class: 'form-control', data: {target: 'preview-container'}, label: false %>
# ...etc... not the data-target attribute has the class name of the preview div

and then you can really simplify your callback to something like:

var color = $(this).minicolors('rgbaString');
var trgt = $(this).data('target');
$('#'+trgt).css('background-color', color);