Zain
Zain

Reputation: 662

When input is focus or filled in then show div jquery

I'm trying to get the condition, when input is focus or filled in then show a div on each input element.

On focus it is working fine, but not able to get this work on filled input.

$('.field').focus(function() {
  $('.placeholder-text').hide();
  var i = 0;

  $('.field').each(function() {
    if ($(this).is(":focus") || $(this).val() > 0) {
      $($('.placeholder-text')[i]).show();
    }
    i++;
  })

  $(document).bind('focusin.placeholder-text click.placeholder-text', function(e) {
    if ($(e.target).closest('.placeholder-text, .field').length) return;
    $(document).unbind('.placeholder-text');
    $('.placeholder-text').fadeOut('medium');
  });
});
$('.placeholder-text').hide();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="name" class="field" name="name" type="text" placeholder="First Name" />
<div class="placeholder-text" for="name">First Name</div>

<input id="lname" class="field" type="text" name="lname" placeholder="Last Name" />
<span class="placeholder-text" for="lname">Last Name</span>

Upvotes: 0

Views: 2130

Answers (3)

Code_Ninja
Code_Ninja

Reputation: 1877

I have made some changes to your HTML structure and I have given some CSS too. I have optimized the jQuery code and it is according to your requirements. Please have a look.

$(".first-name #name, .last-name #lname").on("focus", function() {
  $(this).parent().find(".placeholder-text").show();
});
$(".first-name #name, .last-name #lname").blur("focus", function() {
  $(this).parent().find(".placeholder-text").hide();
  if ($(this).val() == '' || $(this).val() == null) {
    $(this).parent().find(".placeholder-text").show();
  }
});
.placeholder-text {
  display: none;
}

.flex-box {
  display: flex;
}

.first-name,
.last-name {
  display: inline;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="flex-box">
  <div class="first-name">
    <input id="name" class="field" name="name" type="text" placeholder="First Name" />
    <div class="placeholder-text" for="name">First Name</div>
  </div>
  <div class="last-name">
    <input id="lname" class="field" type="text" name="lname" placeholder="Last Name" />
    <span class="placeholder-text" for="lname">Last Name</span>
  </div>
</div>

I hope this was helpful.

Upvotes: 0

David Thomas
David Thomas

Reputation: 253486

While this is, of course, possible with JavaScript – and any of its libraries – it's also possible using pure CSS, if you're able to add the required attribute to the <input> elements, and then styling the visibility of the adjacent .placeholder-text element with the :valid psuedo-class:

input:focus+.placeholder-text,
input:valid+.placeholder-text {
  opacity: 1;
}

Note that I've used a transition of the element's opacity to adjust the visibility of the .placeholder-text elements to avoid the jarring effect of the sudden appearance/disappearance inherent in using display: none/display: initial (or display: block).

body {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}

input+.placeholder-text {
  opacity: 0;
  transition: opacity 0.2s linear;
}

input:focus+.placeholder-text,
input:valid+.placeholder-text {
  opacity: 1;
}
<input id="name" class="field" name="name" type="text" placeholder="First Name" required />
<div class="placeholder-text" for="name">First Name</div>

<input id="lname" class="field" type="text" name="lname" placeholder="Last Name" required />
<span class="placeholder-text" for="lname">Last Name</span>

It's also possible – with CSS – using the :placeholder-shown pseudo-class; though this depends on the browser compatibility you require (Internet Explorer, Edge and Opera Mini have no support as I write); the :placeholder-shown pseudo-class matches an <input> element if it's placeholder value is currently visible:

body {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}

input + .placeholder-text {
  opacity: 0;
  transition: opacity 0.2s linear;
}

input:not(:placeholder-shown) + .placeholder-text {
  opacity: 1;
}
<input id="name" class="field" name="name" type="text" placeholder="First Name" />
<div class="placeholder-text" for="name">First Name</div>

<input id="lname" class="field" type="text" name="lname" placeholder="Last Name" />
<span class="placeholder-text" for="lname">Last Name</span>

Or, to simplify the CSS selector and avoid the use of the :not() negation operator:

body {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}

input:placeholder-shown+.placeholder-text {
  opacity: 0;
}

input+.placeholder-text {
  opacity: 1;
  transition: opacity 0.2s linear;
}
<input id="name" class="field" name="name" type="text" placeholder="First Name" required />
<div class="placeholder-text" for="name">First Name</div>

<input id="lname" class="field" type="text" name="lname" placeholder="Last Name" required />
<span class="placeholder-text" for="lname">Last Name</span>

References:

Upvotes: 1

mplungjan
mplungjan

Reputation: 178403

  1. use .on instead of .bind, but do not bind on each and every focus like you are now
  2. bind on focus, blur and on input
  3. there is no "for" except for labels

$(".field").on("input", function() {
  $(this).next().toggle(this.value != "");
});
$(".field").on("blur", function() {
  if (this.value == "") $(this).next().fadeOut('medium');
})
$(".field").on("focus", function() {
  $(this).next().fadeIn('medium');
})
.placeholder-text { display:none }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="name" class="field" name="name" type="text" placeholder="First Name" /><span class="placeholder-text">First Name</span><br/>

<input id="lname" class="field" type="text" name="lname" placeholder="Last Name" /><span class="placeholder-text">Last Name</span>

Upvotes: 1

Related Questions