#jquery #css #knockout.js
Вопрос:
HTML-код выглядит следующим образом и создает вкладки в верхней части экрана для навигации по нескольким частям программы.
<ul id="navigationMenuTop" class="nav navbar-nav" data-bind="foreach: getRoutes">
<li data-bind="css: { active: isActive() }">
<a data-bind="attr: { href: ... } >
Теперь мне нужно осветить одну из этих вкладок на случай, если определенная часть программы нуждается во внимании пользователей. Проверка этих вниманий выполняется каждые 10 минут, и вкладка должна быть выделена, если проверка возвращает значение true. У меня есть эта строка для выделения в модели представления в операторе if.
$('#navigationMenuTop a[href*="registration"]').parent().css('background-color', '#ff4500');
Проблема в том, что вкладка, которая меняет цвет, не является активной вкладкой, и цвет текста будет серым из-за того, что он неактивен. Просто установив его активным, вы измените не только цвет текста, а это не вариант.
Как изменить цвет текста неактивного элемента списка?
Комментарии:
1. Как именно выполняется эта проверка? Не могли бы вы опубликовать соответствующий код? Вероятно, есть лучший способ, чем смешивать KO с jQuery подобным образом, что является своего рода плохой практикой.
2. Проверка выполняется путем вызова внешнего API, который возвращает значение true при наличии какого-либо уведомления для пользователя. Внешний API проверяет базу данных, в которой хранится состояние сообщений, отправляемых внешним экземплярам, таким как правительство.
Ответ №1:
Я думаю, что я немного переборщил … но вот оно что. Вы можете щелкнуть строку, и она будет выделена, строки выделяются, когда они требуют внимания,… все в нокауте, никакого jquery ..
class Item {
constructor(id, name) {
this.id = id;
this.name = ko.observable(name);
}
}
class ViewModel {
constructor() {
this.items = ko.observableArray([]);
this.active = ko.observable(null);
this.attentions = ko.observableArray([]);
this.getItems()
.then(items => {
this.items(items);
setInterval(() => {
this.getAttentions()
.then(items => {
this.attentions(items);
})
}, 3000);
})
.catch(error => {
console.log(error);
});
}
async getItems(resolve, reject) {
return new Promise((resolve, reject) => {
const items = [
new Item(1, 'foo'), new Item(2, 'bar'), new Item(3, 'this'),
new Item(4, 'is'), new Item(5, 'tedious')
];
setTimeout(() => resolve(items), 300);
});
}
async getAttentions(resolve, reject) {
return new Promise((resolve, reject) => {
const items = this.getRandom(this.items(), 2);
setTimeout(() => resolve(items), 300);
});
}
toggleActive(item) {
const active = this.active();
if (active amp;amp; active === item) this.active(null);
else this.active(item);
}
getRandom(arr, n) {
var result = new Array(n),
len = arr.length,
taken = new Array(len);
if (n > len)
throw new RangeError("getRandom: more elements taken than available");
while (n--) {
var x = Math.floor(Math.random() * len);
result[n] = arr[x in taken ? taken[x] : x];
taken[x] = --len in taken ? taken[len] : len;
}
return resu<
}
hasAttention(item) {
return this.attentions().find(x => x.id === item.id);
}
}
ko.applyBindings(new ViewModel());
table tbody tr {
color: #999;
}
table tbody tr.item-active {
background-color: rgba(1,1,1,.2);
color: #333;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>!</th>
</tr>
</thead>
<tbody data-bind="foreach:{ data: $root.items, as: 'item' }">
<tr data-bind="css: { 'item-active': $root.active() == item }, click: () => $root.toggleActive(item)">
<td data-bind="text: id"></td>
<td data-bind="text: name"></td>
<td data-bind="style: {'background-color': $root.hasAttention(item) ? 'red' : 'transparent'}"></td>
</tr>
</tbody>
</table>
Ответ №2:
Поэтому я попробовал еще кое-что, и это сработало…
$('#navigationMenuTop a[href*="registration"]').css('color', '#000000');