1

For each checkbox that is checked, I am trying to run the function below for changing the color to white / black depending on the darkness of the background-color. However the third checkbox is supposed to be dark enough to change the text color to white, but it isn't executing.

   function isDark(color) {
    var match = /rgb\((\d+).*?(\d+).*?(\d+)\)/.exec(color);
    return (
      (match[1] & 255) + (match[2] & 255) + (match[3] & 255) < 3 * 256 / 2
    );
  }

Trying to call using:

label.css(
  "color",
  isDark(label.css("background-color")) ? "white" : "black"
);

Here is a reference codepen with the function working on its own:

https://codepen.io/moofawsaw/pen/RmZWaL

$(document).ready(function() {
  function isDark(color) {
    var match = /rgb\((\d+).*?(\d+).*?(\d+)\)/.exec(color);
    return (match[1] & 255) + (match[2] & 255) + (match[3] & 255) < 3 * 256 / 2;
  }
  $(".item").each(function() {
    var item = $(this).find(".input");
    var color = $(this)
      .find("label")
      .attr("data-color");
    item.change(function() {
      var label = $(this).closest(".item");
      var dot = $(this)
        .closest(".item")
        .find(".dot");
      var cancel = $(this)
        .closest(".item")
        .find(".cancel");
      if ($(this).prop("checked")) {
        var val = 0;
        dot.css({
          "-webkit-transform": "scale(" + val + ")",
          "-moz-transform": "scale(" + val + ")",
          "-ms-transform": "scale(" + val + ")",
          "-o-transform": "scale(" + val + ")",
          transform: "scale(" + val + ")",
          width: "0px"
        });
        label.css("background-color", color);
        cancel.css("display", "flex");
        label.css(
          "color",
          isDark(label.css("background-color")) ? "white" : "black"
        );
      } else {
        var val = 1;
        label.css("background-color", "");
        dot.css({
          "-webkit-transform": "scale(" + val + ")",
          "-moz-transform": "scale(" + val + ")",
          "-ms-transform": "scale(" + val + ")",
          "-o-transform": "scale(" + val + ")",
          transform: "scale(" + val + ")",
          width: "12px"
        });
        cancel.css("display", "none");
        label.css("color", "");
      }
    });
  });
});
label {
  display: flex;
  align-items: center;
  margin-left: 6px;
  font-size: 12px;
  line-height: 16px;
  font-weight: 400;
  padding: 4px 0;
  font-family: Roboto Mono, arial, sans-serif;
  letter-spacing: -0.2px;
  user-select: none;
  cursor: pointer;
  transition: all 0.25s ease;
}

input {
  display: none;
  visibility: hidden;
}

.boxes {
  display: flex;
  padding: 3rem
}

.item {
  background-color: white;
  padding-left: 8px !important;
  padding-right: 8px !important;
  border: 1px solid #dadce0;
  border-radius: 6px;
  display: flex;
  align-items: center;
  margin: .3rem;
  transition-property: all;
  transition-duration: 0.1s;
  transition-timing-function: ease-in-out;
}

.cancel {
  padding: 0px 6px;
  display: none;
  transition: all 0.25s ease;
}

.dot {
  border-radius: 50%;
  width: 12px;
  height: 12px;
  transition: all 0.25s ease;
}

.item:nth-child(1) .dot {
  background: rgb(255, 64, 129);
}

.item:nth-child(2) .dot {
  background: rgb(49, 231, 182);
}

.item:nth-child(3) .dot {
  background: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="boxes">
  <div class="item">
    <span class="dot"></span>
    <label data-color="rgb(255, 64, 129)" class="checkbox" for="one">
    <input class="input" id="one" type="checkbox">Lobster
          <i class="far fa-times cancel"></i>
  </label>
  </div>
  <div class="item">
    <span class="dot"></span>
    <label data-color="rgb(49, 231, 182)" class="checkbox" for="two">
    <input class="input" id="two" type="checkbox">Tuna  
          <div class="cancel">x</div>
  </label>
  </div>
  <div class="item">
    <span class="dot"></span>
    <label data-color="blue" class="checkbox" for="three">
    <input class="input" id="three" type="checkbox">Pine 
          <div class="cancel">x</div>
  </label>
  </div>
</div>

1
  • return (match[ 0 ] & 255) + (match[ 1 ] & 255) + (match[ 2 ] & 255) < 3 * 256 / 2; Commented May 19, 2019 at 5:15

1 Answer 1

1

Update

Another demo has been added. I wrote a mini-plugin that animates .dot and .cancel. See Demo 2


"However the third checkbox is supposed to be dark enough to change the text color to white, but it isn't executing."

If isDark() were to actually work (which it actually didn't), the third button would've still remain unchanged. The reason why is because it's data-color attribute had "blue" as the value when it should've been rgb(0,0,255). isDark() will return false because "blue" is an invalid argument. Even if it were correct isDark() would always return false because it had so many syntax errors:

function isDark(color) {
  var match = /rgb\((\d+).*?(\d+).*?(\d+)\)/.exec(color);
  return (match[1] & 255) + (match[2] & 255) + (match[3] & 255) < 3 * 256 / 2;
}
  1. Using regex to extract the numbers is a bad idea. Since the numbers are from an arbitrary source (data-color which is data-rgb in the demo), just keep the numbers like so: data-rgb="0,0,255".

  2. The .exec() method will return only an array of one string for two reasons: 1. it needs to run a while loop to continue searching for multiple matches. 2. The regex will match the whole string once because it must match 3 separate numbers. So match[1], match[2], and match[3] never existed, only match[0] (arrays are 0 index).

  3. Where did you find this: ... & 255)? It makes completely no sense at all. Also 3 * 256 / 2 is simply 384 (it's the sum of rgb(128,128,128) which is the color between black and white...grey).

So the whole OP code was changed isDark() was just two lines but had the most discrepancies. The rest of the HTML, CSS, and JavaScript has been changed more for the sake of efficiency than for errors.

Demo 1

$(':checkbox').on('change', function(e) {
  var item = $(this).closest(".item");
  var label = $(this).next("label");
  var dot = label.find(".dot");
  var cancel = label.find(".cancel");
  var color = label.data('rgb');
  var rgb = `rgb(${color})`;
  var contrast = darkness(color) ? "black" : "white";

  if (this.checked) {
    dot.toggleClass('off on');
    item.css({
      "background-color": rgb,
      "color": contrast
    });
    cancel.css('color', contrast);
  } else {
    dot.toggleClass('off on');
    item.css({
      "background-color": "#fff",
      "color": '#000'
    });
    cancel.css('color', 'white');
  }
});

function darkness(color) {
  color.replace(/^\D+|\)/g, '').trim();
  //console.log(color);
  var rgb = color.split(',');
  //console.log(rgb);
  var final = (parseInt(rgb[0], 10) + parseInt(rgb[1], 10) + parseInt(rgb[2], 10));
  //console.log(final);
  if (final < 384) {
    return false;
  }
  return true;
}
label {
  display: flex;
  align-items: center;
  font: 400 12px/16px Roboto Mono, monospace;
  letter-spacing: -0.2px;
  padding: 4px 0;
  margin-left: 6px;
  user-select: none;
  cursor: pointer;
  transition: all 0.25s ease;
}

input {
  display: none;
}

.boxes {
  display: flex;
  padding: 3rem;
  list-style: none;
}

.item {
  display: flex;
  align-items: center;
  background-color: #fff;
  min-width: 100px;
  border: 1px solid #dadce0;
  border-radius: 6px;
  padding-left: 8px;
  padding-right: 8px;
  margin: 0.3rem;
  transition: 0.1s ease-in-out;
}

.text {
  display: inline-block;
  min-width: 50px;
}

.cancel {
  display: inline-block;
  color: #fff;
  padding: 0px 6px;
  transition: all 0.25s ease;
}

.dot {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  margin-right: 20px;
  transition: all 0.25s ease;
}

.dot.off {
  transform: scale(0);
}

.dot.on {
  transform: scale(1);
}

#i0+label .dot {
  background-color: rgb(255, 64, 129);
}

#i1+label .dot {
  background-color: rgb(49, 231, 182);
}

#i2+label .dot {
  background-color: rgb(0, 0, 255);
}
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono&display=swap" rel="stylesheet">
<link href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" rel="stylesheet" crossorigin="anonymous">

<ul class="boxes">

  <li class="item">
    <input id="i0" type="checkbox">
    <label data-rgb="255,64,129" for="i0">
    <mark class="dot on"></mark>
    <b class='text'>Lobster</b>
    <i class="fas fa-times cancel"></i>
  </label>
  </li>

  <li class="item">
    <input id="i1" type="checkbox">
    <label data-rgb="49,231,182" for="i1">
    <mark class="dot on"></mark>
    <b class='text'>Tuna</b>
    <i class="fas fa-times cancel"></i>
  </label>
  </li>

  <li class="item">
    <input id="i2" type="checkbox">
    <label data-rgb="0,0,255" for="i2">
    <mark class="dot on"></mark>
    <b class='text'>Pine</b>
    <i class="fas fa-times cancel"></i>
  </label>
  </li>

</ul>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


Demo 2

$(function() {

  $(':checkbox').on('change', function(e) {
    var item = $(this).parent();
    var dot = $(this).next();
    var text = dot.next();
    var cancel = text.next();
    var color = $(this).val();
    var rgb = `rgb(${color})`;
    var contrast = darkness(color) ? "black" : "white";

    if (this.checked) {
      item.css({
        "background-color": rgb,
        "color": contrast
      });

      dot.toggleClass('on off');
      cancel.css('color', contrast).toggleClass('on off');
    } else {
      item.css({
        "background-color": "#fff",
        "color": '#000'
      });

      dot.toggleClass('on off');
      cancel.toggleClass('on off');
    }
    dot.icons();
    cancel.icons();
  });

  function darkness(color) {
    color.replace(/^\D+|\)/g, '').trim();
    //console.log(color);
    var rgb = color.split(',');
    //console.log(rgb);
    var final = (parseInt(rgb[0], 10) + parseInt(rgb[1], 10) + parseInt(rgb[2], 10));
    //console.log(final);
    if (final < 384) {
      return false;
    }
    return true;
  }

  (function($) {
    $.fn.icons = function() {
      return this.each(function() {
        if ($(this).hasClass('off')) {
          $(this).animate({
            'transform': 'scale(0)',
            'width': '0',
          }, 250);
          $(this).hide();
        } else if ($(this).hasClass('on')) {
          $(this).animate({
            'transform': 'scale(1)',
            'width': '12px'
          }, 250);
          $(this).show();
        } else {
          return false;
        }
      });
    }
  })(jQuery);
  $('.dot, .cancel').icons();
});
.boxes {
  display: flex;
  justify-content: space-around;
  width: max-content;
  padding: 3rem;
}

.item {
  display: flex;
  align-items: center;
  width: fit-content;
  background-color: #fff;
  border: 1px solid #dadce0;
  border-radius: 6px;
  padding: 0 8px;
  margin: 0 4px;
  cursor: pointer;
  transition: 0.15s ease;
}

input {
  display: none;
}

.dot {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  transition: all 0.25s ease-out;
}

.text {
  font: 700 12px/16px Roboto Mono, monospace;
  letter-spacing: -0.2px;
  padding: 4px 0;
  margin: 0 6px;
  user-select: none;
  transition: all 0.25s ease;
}

.text::before {
  content: attr(value);
}

.cancel {
  display: none;
  color: #000;
  font-size: 12px;
  width: 12px;
  transition: all 0.35s ease;
}

#i0+.dot {
  background-color: rgb(255, 64, 129);
}

#i1+.dot {
  background-color: rgb(49, 231, 182);
}

#i2+.dot {
  background-color: rgb(0, 0, 255);
}
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono&display=swap" rel="stylesheet">
<link href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" rel="stylesheet" crossorigin="anonymous">

<form class="boxes">

  <label class="item" for='i0'>
    <input id="i0" type="checkbox" value="255,64,129">
    <mark class="dot on"></mark>
    <output class='text' for='i0' value='Lobster'>
    </output>
    <i class="fas fa-times cancel off"></i>
  </label>

  <label class="item" for='i1'>
    <input id="i1" type="checkbox" value="49,231,182">
    <mark class="dot on"></mark>
    <output class='text' for='i1' value='Tuna'></output>
    <i class="fas fa-times cancel off"></i>
  </label>

  <label class="item" for='i2'>
    <input id="i2" type="checkbox" value="0,0,255">
    <mark class="dot on"></mark>
    <output class='text' for='i2' value='Clam'></output>
    <i class="fas fa-times cancel off"></i>
  </label>

</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Sign up to request clarification or add additional context in comments.

1 Comment

I need to preserve the animation as it was in the question

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.