Поиск идентификатора родительского div с помощью JQuery

99

У меня есть такой html:

<div id="1">
    <p>
        Volume = <input type="text" />
        <button rel="3.93e-6" class="1" type="button">Check answer</button>
    </p>
    <div></div>
</div>

и некоторые JS вроде этого:

$("button").click(function () {
    var buttonNo = $(this).attr('class');
    var correct = Number($(this).attr('rel'));

    validate (Number($("#"+buttonNo+" input").val()),correct);
    $("#"+buttonNo+" div").html(feedback);
});

Я бы очень хотел, чтобы на кнопке не было class = "1" (я знаю, что числовые классы недействительны, но это WIP!), Чтобы я мог определить buttonNo на основе id родительского div. В реальной жизни есть несколько таких разделов.

  1. Как мне найти идентификатор div, являющегося родительским элементом кнопки.

  2. Каким будет более семантический способ сохранить ответ в коде кнопки. Я хочу сделать это максимально надежным, чтобы непрограммист мог копировать и вставлять, не ломая ничего!

Рич Брэдшоу
источник

Ответы:

212

Вы можете использовать делегирование событий в родительском div. Или используйте ближайший метод, чтобы найти родительский элемент кнопки.

Самый простой из двух, вероятно, самый близкий.

var id = $("button").closest("div").prop("id");
отметка
источник
6
Мне очень нравится closest, потому что вы можете делать что-то вроде .closest ("div.foo"), а код не привязан к структуре.
Марк
2
Спасибо, я собирался выполнить рекурсивную функцию .... тогда я знал, что в jquery что-то уже есть ... в моем случае я использовал $ ("#" + id) .closest ("div.form-group"), чтобы найти родительский div, у которого был класс группы форм.
cabaji99
47

1.

$(this).parent().attr("id");

2.

Способов должно быть много! Можно было бы скрыть элемент, содержащий ответ, например

<div>
    Volume = <input type="text" />
    <button type="button">Check answer</button>
    <span style="display: hidden">3.93e-6&lt;/span>
    <div></div>
</div>

А затем используйте код jQuery, аналогичный приведенному выше, чтобы получить его:

$("button").click(function () 
{
    var correct = Number($(this).parent().children("span").text());
    validate ($(this).siblings("input").val(),correct);
    $(this).siblings("div").html(feedback);
});

имейте в виду, что если вы поместите ответ в клиентский код, они его увидят :) Лучший способ сделать это - проверить его на стороне сервера, но для приложения с ограниченными возможностями это может не быть проблемой.

Роб Грант
источник
Я понятия не имею, как отформатировать HTML в этом редакторе, но это кажется более простым способом получить родительский элемент, чем материал Pim ('div: eq (0)'); если я здесь не упускаю тонкости, тогда все элементы html имеют одного прямого родителя, который вы просто получаете с помощью parent ().
Роб Грант,
parent действительно вернет ближайшего родителя, однако, что произойдет, если он решит, что он хочет добавить набор полей или что-то еще вокруг вопроса, но внутри Div.
Пим Ягер,
На самом деле в его собственном примере это вернет <p>
Пим Ягер
Действительно, если добавить больше div, тогда «div: eq (0)» может быть неправильным. Измените структуру, измените код, который ее анализирует :) И да, я упростил пример до минимума html, необходимого для примера; он должен дважды вызвать parent.
Роб Грант,
По какой-то причине, когда я использовал parent (), я не мог получить доступ к attr (id), мне пришлось обернуть результат таким образом $(parent[0]).attr('id')после того, как мне понравились несколько родительских селекторов.
Петр Кула
11

Попробуй это:

$("button").click(function () {
    $(this).parents("div:first").html(...);
});
Буу Нгуен
источник
7

Чтобы получить идентификатор родительского div:

$(buttonSelector).parents('div:eq(0)').attr('id');

Кроме того, вы можете немного реорганизовать свой код:

$('button').click( function() {
 var correct = Number($(this).attr('rel'));
 validate(Number($(this).siblings('input').val()), correct);
 $(this).parents('div:eq(0)').html(feedback);
});

Теперь нет необходимости в классе кнопок

объяснение
eq (0) означает, что вы выберете один элемент из объекта jQuery, в данном случае это элемент 0, то есть первый элемент. http://docs.jquery.com/Selectors/eq#index
$ (selector) .siblings (siblingsSelector) выберет всех братьев и сестер (элементы с одним родителем), которые соответствуют siblingsSelector http://docs.jquery.com/Traversing / siblings # expr
$ (selector) .parents (parentSelector) выберет все родительские элементы, соответствующие селектору, которые соответствуют родительскому селектору. http://docs.jquery.com/Traversing/parents#expr
Таким образом: $ (selector) .parents ('div: eq (0)'); будет соответствовать первому родительскому div элементов, соответствующих селектору.

Вам следует взглянуть на документацию jQuery, особенно на селекторы и обход:

Пим Ягер
источник
Просто и легко! Почему div: eq (0)? Что это значит?
Рич Брэдшоу,
Я думаю, что 'div: eq (0)' будет неправильным, если все это будет заключено хотя бы в один div, потому что вы выполняете абсолютный обход DOM, а не относительный. Что было бы хорошо, если бы первый элемент был «ближайшим» родителем, но это говорит об обратном: tinyurl.com/bbegow
Роб Грант
1
(отсюда и использование parent ())
Роб Грант
5

Это легко сделать, выполнив:

$(this).closest('table').attr('id');

Вы прикрепляете это к любому объекту внутри таблицы, и он вернет вам идентификатор этой таблицы.

Хамид
источник
3

В JQUery есть метод .parents () для перемещения вверх по дереву DOM, с которого вы можете начать.

Если вы заинтересованы в том, чтобы сделать это более семантическим способом, я не думаю, что использование атрибута REL на кнопке - лучший способ семантически определить «это ответ» в вашем коде. Я бы порекомендовал что-то в этом роде:

<p id="question1">
    <label for="input1">Volume =</label> 
    <input type="text" name="userInput1" id="userInput1" />
    <button type="button">Check answer</button>
    <input type="hidden" id="answer1" name="answer1" value="3.93e-6" />
</p>

и

$("button").click(function () {
    var correctAnswer = $(this).parent().siblings("input[type=hidden]").val();
    var userAnswer = $(this).parent().siblings("input[type=text]").val();
    validate(userAnswer, correctAnswer);
    $("#messages").html(feedback);
});

Не совсем уверен, как работают ваша проверка и отзывы, но идею вы поняли.

Попугаи
источник
0

find () и closest () кажется немного медленнее, чем:

$(this).parent().attr("id");
Крис
источник
$(this).parent().parent().attr("id");?
Алехандро Иван