Zackskeeter
Zackskeeter

Reputation: 609

Adding Placeholder attributes base on input label with PURE JS - no jQuery

I need to get the label of each element and apply it to the input as a placeholder attribute, I get about half way though but cannot seem to get just the text of the element in order to add a attribute

Please note that i am not able to use jQuery in any regard

JS:

var elements = document.querySelectorAll('p.form-field');
Array.prototype.forEach.call(elements, function(el, i){
  var chel = el.querySelectorAll('.field-label');
  console.log(chel.textContent);
});

HTML:

<form accept-charset="UTF-8" method="post" action="nottelling" class="form" id="pardot-form">
    <p class="form-field first_name pd-text required ">
        <label class="field-label" for="25492_61334pi_25492_61334">First Name</label>
        <input type="text" name="25492_61334pi_25492_61334" id="25492_61334pi_25492_61334" value="" class="text" size="30" maxlength="32" onchange="" /> 
    </p>

    <div id="error_for_25492_61334pi_25492_61334" style="display:none"></div>

    <p class="form-field last_name pd-text required ">
        <label class="field-label" for="25492_61336pi_25492_61336">Last Name</label>
        <input type="text" name="25492_61336pi_25492_61336" id="25492_61336pi_25492_61336" value="" class="text" size="30" maxlength="32" onchange="" /> 
    </p>

    <div id="error_for_25492_61336pi_25492_61336" style="display:none"></div>

    <p class="form-field email pd-text required ">
        <label class="field-label" for="25492_61338pi_25492_61338">Email</label>
        <input type="text" name="25492_61338pi_25492_61338" id="25492_61338pi_25492_61338" value="" class="text" size="30" maxlength="255" onchange="piAjax.auditEmailField(this, 25492, 61338, 12545572);" /> 
    </p>

    <div id="error_for_25492_61338pi_25492_61338" style="display:none"></div>

    <p class="form-field company pd-text required ">
        <label class="field-label" for="25492_61340pi_25492_61340">Company</label>
        <input type="text" name="25492_61340pi_25492_61340" id="25492_61340pi_25492_61340" value="" class="text" size="30" maxlength="100" onchange="" /> 
    </p>

    <div id="error_for_25492_61340pi_25492_61340" style="display:none"></div>

    <p style="position:absolute; width:190px; left:-9999px; top: -9999px;visibility:hidden;">
        <label for="pi_extra_field">Comments</label>
        <input type="text" name="pi_extra_field" id="pi_extra_field" /> 
    </p>

    <input name="_utf8" type="hidden" value="&#9731;" />

    <p class="submit">
        <input type="submit" accesskey="s" value="Send Message" /> 
    </p>

    <input type="hidden" name="hiddenDependentFields" id="hiddenDependentFields" value="" />
</form>

Upvotes: 0

Views: 4097

Answers (3)

David Thomas
David Thomas

Reputation: 253308

While the earlier answers work, I'd suggest a simpler approach, such as:

function placeholderLabels() {
  // get <input> elements that are in a <p> and follow a <label>:
  var inputs = document.querySelectorAll('p label + input');

  // iterate over those <input> elements:
  Array.prototype.forEach.call(inputs, function(input) {
  // input is the current <input> from the NodeList over which we're
  // iterating, here we set its placeholder property to either:
  // the textContent of the first <label> associated with the <input>
  // or to an empty string, if there's no associated <label>:
    input.placeholder = input.labels.length ? input.labels[0].textContent.trim() : '';
  });
}

placeholderLabels();

function placeholderLabels() {
  var inputs = document.querySelectorAll('p label + input');
  Array.prototype.forEach.call(inputs, function(input) {
    input.placeholder = input.labels.length ? input.labels[0].textContent.trim() : '';
  });
}

placeholderLabels();
label {
  display: inline-block;
  width: 7em;
}
p.required label::after {
  content: '*';
}
<form accept-charset="UTF-8" method="post" action="nottelling" class="form" id="pardot-form">
  <p class="form-field first_name pd-text required ">
    <label class="field-label" for="25492_61334pi_25492_61334">First Name</label>
    <input type="text" name="25492_61334pi_25492_61334" id="25492_61334pi_25492_61334" value="" class="text" size="30" maxlength="32" onchange="" />
  </p>

  <div id="error_for_25492_61334pi_25492_61334" style="display:none"></div>

  <p class="form-field last_name pd-text required ">
    <label class="field-label" for="25492_61336pi_25492_61336">Last Name</label>
    <input type="text" name="25492_61336pi_25492_61336" id="25492_61336pi_25492_61336" value="" class="text" size="30" maxlength="32" onchange="" />
  </p>

  <div id="error_for_25492_61336pi_25492_61336" style="display:none"></div>

  <p class="form-field email pd-text required ">
    <label class="field-label" for="25492_61338pi_25492_61338">Email</label>
    <input type="text" name="25492_61338pi_25492_61338" id="25492_61338pi_25492_61338" value="" class="text" size="30" maxlength="255" onchange="piAjax.auditEmailField(this, 25492, 61338, 12545572);" />
  </p>

  <div id="error_for_25492_61338pi_25492_61338" style="display:none"></div>

  <p class="form-field company pd-text required ">
    <label class="field-label" for="25492_61340pi_25492_61340">Company</label>
    <input type="text" name="25492_61340pi_25492_61340" id="25492_61340pi_25492_61340" value="" class="text" size="30" maxlength="100" onchange="" />
  </p>

  <div id="error_for_25492_61340pi_25492_61340" style="display:none"></div>

  <p style="position:absolute; width:190px; left:-9999px; top: -9999px;visibility:hidden;">
    <label for="pi_extra_field">Comments</label>
    <input type="text" name="pi_extra_field" id="pi_extra_field" />
  </p>

  <input name="_utf8" type="hidden" value="&#9731;" />

  <p class="submit">
    <input type="submit" accesskey="s" value="Send Message" />
  </p>

  <input type="hidden" name="hiddenDependentFields" id="hiddenDependentFields" value="" />
</form>

It's worth reiterating at this point, however, that this is not a good user-interface; the placeholder should not replace the <label>, and if used should provide some guidance on what the <input> expects, such as the format or an expected value.

Upvotes: 2

Jukka K. Korpela
Jukka K. Korpela

Reputation: 201528

You’re close: the problem is just that you are trying to use the object returned by the second querySelectorAll as if it were an element. It returns a collection, even when there is just one matching element. If you know that only one element matches it, simply index it with a zero. The same way you can access the input element, if you know there is only one such element inside each p element. So the essential code can be as follows:

var elements = document.querySelectorAll('p.form-field');
Array.prototype.forEach.call(elements, function(el, i){
  el.querySelectorAll('input')[0].placeholder =
    el.querySelectorAll('.field-label')[0].textContent;
});

There are several possible approaches, depending on the assumptions you make about the source code.

Note: Duplicating label texts as placeholders is useless and disturbing. Replacing label text by placeholders is bad for accessibility and frowened upon in the HTML5 spec. But maybe the operation you are doing has some different purpose.

Upvotes: 0

Benjamin De Cock
Benjamin De Cock

Reputation: 230

var labels = document.querySelectorAll("label");
var i = labels.length;
while (i--) {
  var label = labels.item(i);
  var text = label.textContent;
  label.parentNode.classList.contains("required") && (text += "*");
  label.nextElementSibling.setAttribute("placeholder", text);
}

Upvotes: 5

Related Questions