select и unselect не работает для динамически созданного флажка в js

57
5

Я создал динамически в javascript-скрипте, используя bootstrap js и css. Выбрать и отменить выбор не работает: введите описание изображения здесь

Во втором изображении html создается динамически из js: введите описание изображения здесь. Если я скопирую это и создаю в html, он работает. Как создать динамическое дерево меток?

$(function() {

$('input[type="checkbox"]').change(checkboxChanged);

function checkboxChanged() {
var $this = $(this),
checked = $this.prop("checked"),
container = $this.parent(),
siblings = container.siblings();

container.find('input[type="checkbox"]')
.prop({
indeterminate: false,
checked: checked
})
.siblings('label')
.removeClass('custom-checked custom-unchecked custom-indeterminate')
.addClass(checked ? 'custom-checked' : 'custom-unchecked');

checkSiblings(container, checked);
}

function checkSiblings($el, checked) {
var parent = $el.parent().parent(),
all = true,
indeterminate = false;

$el.siblings().each(function() {
return all = ($(this).children('input[type="checkbox"]').prop("checked") === checked);
});

if (all && checked) {
parent.children('input[type="checkbox"]')
.prop({
indeterminate: false,
checked: checked
})
.siblings('label')
.removeClass('custom-checked custom-unchecked custom-indeterminate')
.addClass(checked ? 'custom-checked' : 'custom-unchecked');

checkSiblings(parent, checked);
}
else if (all && !checked) {
indeterminate = parent.find('input[type="checkbox"]:checked').length > 0;

parent.children('input[type="checkbox"]')
.prop("checked", checked)
.prop("indeterminate", indeterminate)
.siblings('label')
.removeClass('custom-checked custom-unchecked custom-indeterminate')
.addClass(indeterminate ? 'custom-indeterminate' : (checked ? 'custom-checked' : 'custom-unchecked'));

checkSiblings(parent, checked);
}
else {
$el.parents("li").children('input[type="checkbox"]')
.prop({
indeterminate: true,
checked: false
})
.siblings('label')
.removeClass('custom-checked custom-unchecked custom-indeterminate')
.addClass('custom-indeterminate');
}
}
});

* { margin: 0; padding: 0; }

#page-wrap {
margin: auto 0;
}

.treeview {
margin: 10px 0 0 20px;
}

ul {
list-style: none;
}

.treeview li {
background: url(http://jquery.bassistance.de/treeview/images/treeview-default-line.gif) 0 0 no-repeat;
padding: 2px 0 2px 16px;
}

.treeview > li:first-child > label {
/* style for the root element - IE8 supports :first-child
but not :last-child ..... */

}

.treeview li.last {
background-position: 0 -1766px;
}

.treeview li > input {
height: 16px;
width: 16px;
/* hide the inputs but keep them in the layout with events (use opacity) */
opacity: 0;
filter: alpha(opacity=0); /* internet explorer */
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"; /*IE8*/
}

.treeview li > label {
background: url(https://www.thecssninja.com/demo/css_custom-forms/gr_custom-inputs.png) 0 -1px no-repeat;
/* move left to cover the original checkbox area */
margin-left: -20px;
/* pad the text to make room for image */
padding-left: 20px;
}

/* Unchecked styles */

.treeview .custom-unchecked {
background-position: 0 -1px;
}
.treeview .custom-unchecked:hover {
background-position: 0 -21px;
}

/* Checked styles */

.treeview .custom-checked {
background-position: 0 -81px;
}
.treeview .custom-checked:hover {
background-position: 0 -101px;
}

/* Indeterminate styles */

.treeview .custom-indeterminate {
background-position: 0 -141px;
}
.treeview .custom-indeterminate:hover {
background-position: 0 -121px;
}

<body class="skin-blue sidebar-mini" style="height: auto; min-height: 100%;">

<!-- changing values in row -->
<input id="rowNumber" class="form-control " type="hidden">

<div class="wrapper" style="height: auto; min-height: 100%; background-color: #ECEFF4;">
<!-- Main content -->
<section class="content">

<div class="row">
<div class="col-xs-12">
<!-- /.box -->
<div class="box">
<!-- /.box-header -->
<div class="box-body">

<button onclick="addCheckBox()">add</button>
<input id="check" name="checkBoxes">
<div id="page-wrap">
<ul class="treeview">
<li>
<input type="checkbox" name="short" id="short">
<label for="short" class="custom-unchecked">Short Things</label>

<ul id="cc">

</ul>
</li>
</ul>

</div>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
<!-- /.col -->
</div>
<!-- /.row -->
</section>
<!-- /.content -->
</div>
<script src="//code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha256-3edrmyuQ0w65f8gfBsqowzjJe2iM6n0nKciPUp8y+7E=" crossorigin="anonymous"></script>
<script type="text/javascript">
function addCheckBox() {

var listElement = document.getElementById('cc');
var check_value = new Array();
check_value[1] = "Yellow";
check_value[2] = "Red";
check_value[3] = "Green";

var li, checkbox, label, br, a;

var title = document.getElementById('check').value;

for (var i = 1; i <= title; i++) {
li = document.createElement("li");
if (i == title)
{
li.className = "last";
}
checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.name = "short-" + i;
checkbox.id = "short-" + i;
label = document.createElement("label");
label.htmlFor = "short-" + i;
label.className = "custom-unchecked";
label.setAttribute("class", "custom-unchecked");
label.innerHTML = check_value[i];

li.innerHTML += checkbox.outerHTML + label.outerHTML;
listElement.appendChild(li);

/*li.appendChild(checkbox);
//li.appendChild(label);
listElement.appendChild(li);
listElement.appendChild(checkbox);
listElement.appendChild(label); */
}
}
</script>
</body>

спросил(а) 2018-09-24T19:48:00+03:00 2 года назад
1
Решение
80

Как говорит @Alx-lark, проблема, с которой вы сталкиваетесь, заключается в том, что вы привязываетесь к событию изменения при начальной загрузке страницы, но как работает привязка к событию, любые последующие элементы флажка, добавленные на страницу позже, не будут связаны. Решение, упомянутое в его ответе - снятие привязки на ВСЕХ флажках, а затем повторное привязку на ВСЕХ флажках, включая те, которые были добавлены в последнее время, должно работать.

Вы также можете привязать к отдельному флажку, когда вы его добавите, или вы могли бы связать выше элемент, который всегда существует, например document

Это, вероятно, самое легкое изменение, которое можно изменить, изменив линию

$('input[type="checkbox"]').change(checkboxChanged) в $(document).on('change', 'input[type="checkbox"]', checkboxChanged);

Это называется делегированием событий, и вы можете прочитать об этом здесь: https://learn.jquery.com/events/event-delegation/

Делегирование событий позволяет нам присоединить одного прослушивателя событий к родительскому элементу, который будет срабатывать для всех потомков, соответствующих селектору, независимо от того, существуют ли эти потомки или добавлены в будущем.

 function checkboxChanged() {
var $this = $(this),
checked = $this.prop("checked"),
container = $this.parent(),
siblings = container.siblings();

container.find('input[type="checkbox"]')
.prop({
indeterminate: false,
checked: checked
})
.siblings('label')
.removeClass('custom-checked custom-unchecked custom-indeterminate')
.addClass(checked ? 'custom-checked' : 'custom-unchecked');

checkSiblings(container, checked);
}

function checkSiblings($el, checked) {
var parent = $el.parent().parent(),
all = true,
indeterminate = false;

$el.siblings().each(function() {
return all = ($(this).children('input[type="checkbox"]').prop("checked") === checked);
});

if (all && checked) {
parent.children('input[type="checkbox"]')
.prop({
indeterminate: false,
checked: checked
})
.siblings('label')
.removeClass('custom-checked custom-unchecked custom-indeterminate')
.addClass(checked ? 'custom-checked' : 'custom-unchecked');

checkSiblings(parent, checked);
}
else if (all && !checked) {
indeterminate = parent.find('input[type="checkbox"]:checked').length > 0;

parent.children('input[type="checkbox"]')
.prop("checked", checked)
.prop("indeterminate", indeterminate)
.siblings('label')
.removeClass('custom-checked custom-unchecked custom-indeterminate')
.addClass(indeterminate ? 'custom-indeterminate' : (checked ? 'custom-checked' : 'custom-unchecked'));

checkSiblings(parent, checked);
}
else {
$el.parents("li").children('input[type="checkbox"]')
.prop({
indeterminate: true,
checked: false
})
.siblings('label')
.removeClass('custom-checked custom-unchecked custom-indeterminate')
.addClass('custom-indeterminate');
}
}

$(function() {

$(document).on('change', 'input[type="checkbox"]', checkboxChanged);


});

* { margin: 0; padding: 0; }

#page-wrap {
margin: auto 0;
}

.treeview {
margin: 10px 0 0 20px;
}

ul {
list-style: none;
}

.treeview li {
background: url(http://jquery.bassistance.de/treeview/images/treeview-default-line.gif) 0 0 no-repeat;
padding: 2px 0 2px 16px;
}

.treeview > li:first-child > label {
/* style for the root element - IE8 supports :first-child
but not :last-child ..... */

}

.treeview li.last {
background-position: 0 -1766px;
}

.treeview li > input {
height: 16px;
width: 16px;
/* hide the inputs but keep them in the layout with events (use opacity) */
opacity: 0;
filter: alpha(opacity=0); /* internet explorer */
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"; /*IE8*/
}

.treeview li > label {
background: url(https://www.thecssninja.com/demo/css_custom-forms/gr_custom-inputs.png) 0 -1px no-repeat;
/* move left to cover the original checkbox area */
margin-left: -20px;
/* pad the text to make room for image */
padding-left: 20px;
}

/* Unchecked styles */

.treeview .custom-unchecked {
background-position: 0 -1px;
}
.treeview .custom-unchecked:hover {
background-position: 0 -21px;
}

/* Checked styles */

.treeview .custom-checked {
background-position: 0 -81px;
}
.treeview .custom-checked:hover {
background-position: 0 -101px;
}

/* Indeterminate styles */

.treeview .custom-indeterminate {
background-position: 0 -141px;
}
.treeview .custom-indeterminate:hover {
background-position: 0 -121px;
}

<body class="skin-blue sidebar-mini" style="height: auto; min-height: 100%;">

<!-- changing values in row -->
<input id="rowNumber" class="form-control " type="hidden">

<div class="wrapper" style="height: auto; min-height: 100%; background-color: #ECEFF4;">
<!-- Main content -->
<section class="content">

<div class="row">
<div class="col-xs-12">
<!-- /.box -->
<div class="box">
<!-- /.box-header -->
<div class="box-body">

<button onclick="addCheckBox()">add</button>
<input id="check" name="checkBoxes">
<div id="page-wrap">
<ul class="treeview">
<li>
<input type="checkbox" name="short" id="short">
<label for="short" class="custom-unchecked">Short Things</label>

<ul id="cc">

</ul>
</li>
</ul>

</div>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
<!-- /.col -->
</div>
<!-- /.row -->
</section>
<!-- /.content -->
</div>
<script src="//code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha256-3edrmyuQ0w65f8gfBsqowzjJe2iM6n0nKciPUp8y+7E=" crossorigin="anonymous"></script>
<script type="text/javascript">
function addCheckBox() {

var listElement = document.getElementById('cc');
var check_value = new Array();
check_value[1] = "Yellow";
check_value[2] = "Red";
check_value[3] = "Green";

var li, checkbox, label, br, a;

var title = document.getElementById('check').value;

for (var i = 1; i <= title; i++) {
li = document.createElement("li");
if (i == title)
{
li.className = "last";
}
checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.name = "short-" + i;
checkbox.id = "short-" + i;
label = document.createElement("label");
label.htmlFor = "short-" + i;
label.className = "custom-unchecked";
label.setAttribute("class", "custom-unchecked");
label.innerHTML = check_value[i];

li.innerHTML += checkbox.outerHTML + label.outerHTML;
listElement.appendChild(li);

/*li.appendChild(checkbox);
//li.appendChild(label);
listElement.appendChild(li);
listElement.appendChild(checkbox);
listElement.appendChild(label); */
}
}
</script>
</body>

ответил(а) 2018-09-24T22:17:00+03:00 2 года назад
41

С кодовой точки все работает правильно.

Событие, прикрепленное к созданным элементам DOM после загрузки страницы Вы прогамарно, нажав кнопку "Добавить", добавьте новые элементы DOM. Поэтому вы должны отключить старые события (чтобы уменьшить утечку памяти) и создать новый.

В нескольких словах в вашей функции addCheckBox() после создания новых элементов вы должны добавить:

$('input[type="checkbox"]').off('change'); // detach event
$('input[type="checkbox"]').on('change', checkboxChanged); // add new event

ответил(а) 2018-09-24T21:40:00+03:00 2 года назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема