remixdesign remixdesign - 4 months ago 24
CSS Question

Finding Closest Label without being too specific

EDIT

Essentially what I am trying to do is solve "Nearest (previous)" "First" "Label" to a specific class on an input without adding additional markup. Please view my fiddle below to see a few cases. I am aware I can add css etc. to this.. I am looking for a JS solution.

END EDIT

Fiddle Provided below.

I am trying to find a corresponding (previous) label to a class - in multiple use cases - I do not what the HTML to have to be too strict - I'd like to be a able to use this in a variety of solutions...

$(".FINDME")
.siblings("label")
.prepend("<span style='color: magenta;'>* </span>");


The previous works, but not for all instances where the label may not be a sibling or when there are nested divs.

I also tried:

$(".FINDME")
.closest(".row")
.find("label")
.append("<span style='color: magenta;'> *</span>");


this works as well but in the case when there are multiple labels in the
.row
this applies the * to all labels.

I need a solution to find the nearest label to the class.

Fiddle: https://jsfiddle.net/r6Lx4ytg/

Answer

Interesting question :)

I tried to solve this, by considering input control as a center and each time increasing the radius where I search for a label.

If I don't find a label within the current parent object, then I take parent's parent (ancestor), and this goes on till it reach maximum depth.

// comment out either one to see the difference:
//$(".FINDME").siblings("label").prepend("<span style='color: magenta;'>* </span>");
//$(".FINDME").closest(".row").find("label").append("<span style='color: magenta;'> *</span>");

$(".FINDME").each(function(idx, obj) {
  var $obj = $(obj);
  var parent = $obj;
  var depth = 5, // You can define till which depth you can test for nearest label
    currentDepth = 0;
  while (true) {
    parent = parent.parent();
    currentDepth++;
    if (!parent || currentDepth == depth)
      break;
    var labels = parent.find("label");
    if (labels.length > 0) {
      var myLabel = $(labels[0]);
      if (myLabel.find(".star").length == 0)
        myLabel.prepend("<span class='star' style='color: magenta;'>* </span>");
      break;
    }
  }
});
.row {
  margin-top: 10px;
  width: 100%;
}
.row .col-md-2 {
  float: left;
  width: 16.66666666666667%;
}
.row .col-md-6 {
  float: left;
  width: 50%;
}
.row .col-md-10 {
  float: left;
  width: 83.33333333333333%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
  <div class="col-md-2">
    <label>First Name:</label>
  </div>
  <div class="col-md-10">
    <input type="text" value="" class="FINDME" placeholder="First Name" />
  </div>
</div>

<div class="row">
  <label>Middle Name:</label>
  <input type="text" value="" class="FINDME" placeholder="Middle Name" />
</div>

<div class="row">
  <div class="col-md-2">
    <label>Last Name:</label>
  </div>
  <div class="col-md-10">
    <input type="text" value="" class="FINDME" placeholder="Last Name" />
  </div>
</div>

<div class="row">
  <div class="col-md-6">
    <label>Gender:</label>
    <br>
    <div class="FINDME">
      <input type="radio" name="gender" value="male">Male
      <br>
      <input type="radio" name="gender" value="female">Female
      <br>
      <input type="radio" name="gender" value="alien">Alien
    </div>
  </div>
  <div class="col-md-6">
    <label>Food:</label>
    <div class="">
      <input type="checkbox" name="option1" value="Milk">Milk
      <br>
      <input type="checkbox" name="option2" value="Butter">Butter
      <br>
      <input type="checkbox" name="option3" value="Cheese">Cheese
      <br>
    </div>
  </div>
</div>

Link to JS Fiddle https://jsfiddle.net/davidsekar/8xqzupwe/6/