Знайдіть html-ярлик, пов’язаний із заданим входом


110

Скажімо, у мене є форма html. Кожен вхід / вибрати / текстове поле буде мати відповідний <label>з forнабором атрибутів ідентифікатора це компаньйон. У цьому випадку я знаю, що кожен вхід матиме лише одну мітку.

Наприклад, враховуючи елемент введення в javascript - через подію onkeyup, - який найкращий спосіб знайти його пов’язану мітку?


5
Зауважте, що елемент може мати більше однієї мітки, я бачив деякі програми (SAP для однієї), які мають кілька міток на елемент.
Мотті

2
function getInputLabel(thisElement) { var theAssociatedLabel,elementID; elementID = thisElement.id; theAssociatedLabel = thisElement.parentNode.querySelector("label[for='" + elementID + "']"); console.log('theAssociatedLabel.htmlFor: ' + theAssociatedLabel.htmlFor); theAssociatedLabel.style.backgroundColor = "green";//Set the label background color to green };
Алан Уеллс

або просто node.parentNode.querySelector ("label [for = '" + node.id + "']"). внутрішнійHTML; lol
Соломон P

Відповіді:


87

Спочатку скануйте сторінку на предмет міток і призначте посилання на мітку з фактичного елемента форми:

var labels = document.getElementsByTagName('LABEL');
for (var i = 0; i < labels.length; i++) {
    if (labels[i].htmlFor != '') {
         var elem = document.getElementById(labels[i].htmlFor);
         if (elem)
            elem.label = labels[i];         
    }
}

Потім ви можете просто перейти:

document.getElementById('MyFormElem').label.innerHTML = 'Look ma this works!';

Немає необхідності в масиві пошуку :)


Чи можете ви пояснити, чим ваше використання розширеного властивості відрізняється від мого? Я не використовую жодного "масиву пошуку", я використовую об'єкт із властивостями. Існує лише синтаксична різниця між "element.label", "element ['label']" або "lookup ['elementId']". За лаштунками вони те саме .
Томалак

4
Це приємніше, тому що я не повинен тримати окремий об'єкт навколо - зв'язок зберігається безпосередньо з вхідним елементом.
Joel Coehoorn

3
З цим повинен
вчинити

103

Якщо ви використовуєте jQuery, ви можете зробити щось подібне

$('label[for="foo"]').hide ();

Якщо ви не використовуєте jQuery, вам доведеться шукати мітку. Ось функція, яка приймає елемент як аргумент і повертає пов'язану мітку

function findLableForControl(el) {
   var idVal = el.id;
   labels = document.getElementsByTagName('label');
   for( var i = 0; i < labels.length; i++ ) {
      if (labels[i].htmlFor == idVal)
           return labels[i];
   }
}

33

У стандарті HTML5 є labelsвластивість яка вказує на мітки, пов'язані з вхідним елементом.

Таким чином, ви можете використовувати щось подібне (підтримка рідної labelsвласності, але із резервним завантаженням міток у випадку, якщо браузер не підтримує її) ...

var getLabelsForInputElement = function(element) {
    var labels = [];
    var id = element.id;

    if (element.labels) {
        return element.labels;
    }

    id && Array.prototype.push
        .apply(labels, document.querySelector("label[for='" + id + "']"));

    while (element = element.parentNode) {
        if (element.tagName.toLowerCase() == "label") {
            labels.push(element);
        }  
    }

    return labels;
};

// ES6
var getLabelsForInputElement = (element) => {
    let labels;
    let id = element.id;

    if (element.labels) {
        return element.labels;
    }

    if (id) {
        labels = Array.from(document.querySelector(`label[for='${id}']`)));
    }

    while (element = element.parentNode) {
        if (element.tagName.toLowerCase() == "label") {
            labels.push(element);
        }  
    }

    return labels;
};

Ще простіше, якщо ви використовуєте jQuery ...

var getLabelsForInputElement = function(element) {
    var labels = $();
    var id = element.id;

    if (element.labels) {
        return element.labels;
    }

    id && (labels = $("label[for='" + id  + "']")));

    labels = labels.add($(element).parents("label"));

    return labels;
};

4
Не тільки в Chrome, це і в стандарті HTML5 .
Бергі

1
Це повинно бути ваааай. Дякую!
maxhm10

23

Я трохи здивований, що, здається, ніхто не знає, що вам дозволено це робити:

<label>Put your stuff here: <input value="Stuff"></label>

Який не підбере жоден із запропонованих відповідей, але буде маркувати введення правильно.

Ось код, який враховує цей випадок:

$.fn.getLabels = function() {
    return this.map(function() {
        var labels = $(this).parents('label');
        if (this.id) {
            labels.add('label[for="' + this.id + '"]');
        }
        return labels.get();
    });
};

Використання:

$('#myfancyinput').getLabels();

Деякі примітки:

  • Код був написаний для наочності, а не для продуктивності. Можливо, будуть доступні більш ефективні альтернативи.
  • Цей код підтримує отримання міток декількох предметів за один раз. Якщо це не те, що ви хочете, адаптуйте по мірі необхідності.
  • Це все ще не піклується про такі речі, як, aria-labelledbyякби ви використовували це (залишене читачем як вправа).
  • Використання декількох міток - це складний бізнес, коли мова йде про підтримку різних агентів користувача та допоміжних технологій, тому добре перевіряйте та використовуйте на свій страх і ризик тощо.
  • Так, ви можете також реалізувати це, не використовуючи jQuery. :-)

6
Приємно бачити, що хтось викликає неявну асоціацію міток на відміну від того, щоб робити припущення, що завжди буде forатрибут на labelелементі.
Джош Хабдас

14

Раніше ...

var labels = document.getElementsByTagName("LABEL"),
    lookup = {},
    i, label;

for (i = 0; i < labels.length; i++) {
    label = labels[i];
    if (document.getElementById(label.htmlFor)) {
        lookup[label.htmlFor] = label;
    }
}

Пізніше ...

var myLabel = lookup[myInput.id];

Коментар Snarky: Так, ви також можете це зробити з JQuery. :-)


1
Приємно. Я перефактую це трохи, щоб він будував пошук у перший раз, коли я викликаю метод, але він повинен зробити свою справу.
Джоель Куехорн

Я мав на увазі, що ви побудуєте пошук лише один раз.
Томалак

Зверніть увагу, що в ньому була невелика помилка: використовуйте властивість "htmlFor", а не "for", оскільки останнє є зарезервованим словом у JS. Я, як правило, забуваю, що при використанні об’єктів міток ... :-)
Tomalak

У мене є спосіб зробити це без масиву пошуку вище.
FlySwat

Я мав на увазі перемістити код init всередині методу, а не робити це один раз :(
Joel Coehoorn

13

document.querySelector ("label [for =" + vHtmlInputElement.id + "]");

Це дає відповідь на запитання найпростішим та найповнішим способом. Для цього використовується ванільний javascript і працює у всіх належних веб-переглядачах.


Це не дає відповіді на запитання. Одного разу вам достатньо репутація, ви зможете коментувати будь-яку публікацію ; натомість надайте відповіді, які не потребують уточнення від запитувача . - З огляду
loki

1
Це, безумовно, дає відповідь на запитання @loki Тільки тому, що немає додаткового пояснення до нього, це не означає, що він неправильний або не намагався відповісти на нього.
geisterfurz007

Найпростіша і корисна відповідь! Дякую!
iedmrc

8

з jquery ви могли б зробити щось на кшталт

var nameOfLabel = someInput.attr('id');
var label = $("label[for='" + nameOfLabel + "']");

Потенційно пропускає етикетки, хоча це предки.
алекс

4

Якщо ви готові використовувати querySelector (а можете, навіть до IE9, а іноді і IE8!), Інший метод стає життєздатним.

Якщо у вашому полі форми є ідентифікатор, а ви використовуєте forатрибут мітки , у сучасному JavaScript це стає досить простим:

var form = document.querySelector('.sample-form');
var formFields = form.querySelectorAll('.form-field');

[].forEach.call(formFields, function (formField) {
    var inputId = formField.id;
    var label = form.querySelector('label[for=' + inputId + ']');
    console.log(label.textContent);
});

Деякі відзначили багаторазові етикетки; якщо всі вони використовують одне і те ж значення для forатрибута, просто використовуйте querySelectorAllзамість нього querySelectorі перебирайте його, щоб отримати все необхідне.


3

Всі інші відповіді надзвичайно застаріли !!

Все, що вам потрібно зробити, це:

input.labels

HTML5 підтримується всіма основними браузерами вже багато років. Немає абсолютно ніяких причин, щоб вам не довелося робити це з нуля самостійно або поліфікувати! Буквально просто використовуйте, input.labelsі це вирішує всі ваші проблеми.


1
Відповідно до цієї сторінки , input.labelsвона не підтримується IE або Edge, а Firefox лише додав підтримку.
Antti29

@ Antti29 Ви можете додати функціональність за допомогою shim: github.com/termi/ES5-DOM-SHIM Функцію можна додати тут: github.com/termi/ES5-DOM-SHIM/blob/…
ADJenks

2
$("label[for='inputId']").text()

Це допомогло мені отримати мітку елемента введення, використовуючи його ідентифікатор.


2

Відповідь від Gijs була для мене найціннішою, але, на жаль, розширення не працює.

Ось перероблене розширення, яке працює, воно може допомогти комусь:

jQuery.fn.getLabels = function () {
    return this.map(function () {
        var parentLabels = $(this).parents('label').get();
        var associatedLabels = this.id ? associatedLabels = $("label[for='" + this.id + "']").get() : [];
        return parentLabels.concat(associatedLabels);
    });
};

2

Дійсно стисним рішенням з використанням таких функцій ES6, як руйнування та неявна віддача, щоб перетворити його на зручний один вкладиш, було б:

const getLabels = ({ labels, id }) => labels || document.querySelectorAll(`label[for=${id}]`)

Або просто отримати одну мітку, а не NodeList:

const getFirstLabel = ({ labels, id }) => labels && labels[0] || document.querySelector(`label[for=${id}]`)

1

Насправді набагато простіше додати ідентифікатор до мітки у самій формі, наприклад:

<label for="firstName" id="firstNameLabel">FirstName:</label>

<input type="text" id="firstName" name="firstName" class="input_Field" 
       pattern="^[a-zA-Z\s\-]{2,25}$" maxlength="25"
       title="Alphabetic, Space, Dash Only, 2-25 Characters Long" 
       autocomplete="on" required
/>

Тоді ви можете просто використовувати щось подібне:

if (myvariableforpagelang == 'es') {
   // set field label to spanish
   document.getElementById("firstNameLabel").innerHTML = "Primer Nombre:";
   // set field tooltip (title to spanish
   document.getElementById("firstName").title = "Alfabética, espacio, guión Sólo, 2-25 caracteres de longitud";
}

Для роботи Javascript повинен бути функція завантаження тіла.

Просто думка, прекрасно працює для мене.


1

Як уже згадувалося, відповідь (на даний момент) з найвищим рейтингом не враховує можливості вставляти вкладку всередину мітки.

Оскільки ніхто не опублікував відповідь без JQuery, ось моя:

var labels = form.getElementsByTagName ('label');
var input_label = {};
for (var i = 0 ; i != labels.length ; i++)
{
    var label = labels[i];
    var input = label.htmlFor
              ? document.getElementById(label.htmlFor)
              : label.getElementsByTagName('input')[0];
    input_label[input.outerHTML] = 
        (label.innerText || label.textContent); // innerText for IE8-
}

У цьому прикладі для простоти таблиця пошуку безпосередньо індексується вхідними елементами HTML. Це навряд чи ефективно, і ви можете адаптувати його, як завгодно.

Ви можете використовувати форму як базовий елемент або весь документ, якщо ви хочете отримати мітки для декількох форм одночасно.

Не проводяться перевірки на неправильний HTML (кілька чи відсутні вхідні дані всередині міток, відсутні дані з відповідним htmlFor id тощо), але сміливо додайте їх.

Можливо, ви захочете обрізати тексти міток, оскільки пробіли часто є при вкладенні в мітку вводу.


1

Найкраща відповідь справляється чудово, але в більшості випадків це надмірно та неефективно прокручувати всі labelелементи.

Ось ефективна функція, щоб отримати те, labelщо йде з inputелементом:

function getLabelForInput(id)
{
    var el = document.getElementById(id);
    if (!el)
        return null;
    var elPrev = el.previousElementSibling;
    var elNext = el.nextElementSibling;
    while (elPrev || elNext)
    {
        if (elPrev)
        {
            if (elPrev.htmlFor === id)
                return elPrev;
            elPrev = elPrev.previousElementSibling;
        }
        if (elNext)
        {
            if (elNext.htmlFor === id)
                return elNext;
            elNext = elNext.nextElementSibling;
        }
    }
    return null;
}

Для мене цього одного рядка коду було достатньо:

el = document.getElementById(id).previousElementSibling;

У більшості випадків labelсигнал буде дуже близьким або поруч із входом, а це означає, що цикл у вищевказаній функції потрібно лише повторити дуже малу кількість разів.


0

ви спробували скористатися document.getElementbyID ('id'), де id - це ідентифікатор мітки або ситуація, коли ви не знаєте, якого саме шукаєте


Я знаю ідентифікатор вхідного елемента, але не ідентифікатор мітки.
Joel Coehoorn

чи не можна встановити відповідний ідентифікатор для ярлика, такого як input id = 'test' та label id = 'lbl_test'
Josh Mein


0

Для майбутніх шукачів ... Далі йде версія jQuery із прийнятою відповіддю FlySwat:

var labels = $("label");
for (var i = 0; i < labels.length; i++) {
    var fieldId = labels[i].htmlFor;
    if (fieldId != "") {
        var elem = $("#" + fieldId);
        if (elem.length != 0) {
            elem.data("label", $(labels[i]));   
        }
    }
}

Використання:

$("#myFormElemId").data("label").css("border","3px solid red");

+1, але, як я бачу, немає причин використовувати версію jQuery для першого блоку: це не будь-який коротший чи легший для читання текст, і звичайний javascript, ймовірно, буде краще. Приємно мати приклад jQuery, як використовувати його колись створене.
Joel Coehoorn

Очевидно, що для багатьох із нас існує не так багато технічних причин такого підходу, скоріше причина, принаймні в моєму випадку, HR. Уявіть, що у вас є команда, яка включала дизайнерів, інтеграторів і навіть молодших розробників, які у вас сповільнилися, звикли використовувати jQuery. Зберігання речей у парадигмі jQuery може допомогти підвищити продуктивність та зменшити фрустрацію.
ObjectType

Це не дуже jQuery . Чому forпетля закінчилася each()? Чому htmlForзамість цього attr("for")?
алекс

Я думаю, залежить від точки зору. Споживання визначалось jQuery, а не внутрішніми.
ObjectType

0

Я знаю, що це по-старому, але у мене виникли проблеми з деякими рішеннями і вирішити це разом. Я перевірив це на Windows (Chrome, Firefox і MSIE) та OS X (Chrome і Safari) і вважаю, що це найпростіше рішення. Це працює з цими трьома стилями прикріплення етикетки.

<label><input type="checkbox" class="c123" id="cb1" name="item1">item1</label>

<input type="checkbox" class="c123" id="cb2" name="item2">item2</input>

<input type="checkbox" class="c123" id="cb3" name="item3"><label for="cb3">item3</label>

Використання jQuery:

$(".c123").click(function() {
    $cb = $(this);
    $lb = $(this).parent();
    alert( $cb.attr('id') + ' = ' + $lb.text() );
});

Мій JSFiddle: http://jsfiddle.net/pnosko/6PQCw/


Це насправді не працює - це просто повернення тексту батьківського елемента, який іноді буває потрібним текстом.
Джон Хаскалл

0

Я зробив для власних потреб, може бути корисним для когось: JSFIDDLE

$("input").each(function () {
    if ($.trim($(this).prev('label').text()) != "") {
        console.log("\nprev>children:");
        console.log($.trim($(this).prev('label').text()));
    } else {
        if ($.trim($(this).parent('label').text()) != "") {
            console.log("\nparent>children:");
            console.log($.trim($(this).parent('label').text()));
        } else {
            if ($.trim($(this).parent().prev('label').text()) != "") {
                console.log("\nparent>prev>children:");
                console.log($.trim($(this).parent().prev('label').text()));
            } else {
                console.log("NOTFOUND! So set your own condition now");
            }
        }
    }
});

0

Я трохи здивований, що ніхто не пропонує використовувати метод відносин CSS?

у таблиці стилів можна посилатись на мітку із селектора елементів:

<style>

//for input element with class 'YYY'
input.YYY + label {}

</style>

якщо прапорець має ідентифікатор "XXX", мітка буде знайдена через jQuery:

$('#XXX + label');

Ви також можете застосувати .find ('+ label'), щоб повернути мітку з елемента прапорця jQuery, тобто корисно під час циклу:

$('input[type=checkbox]').each( function(){
   $(this).find('+ label');
});

На жаль, слід зазначити, що це спирається на мітку, що надходить безпосередньо після елемента.
Гордон Роуз
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.