removing a HTML list using javascript - javascript

So... I'm making a page that has notifications, a mark as read button and a mark all as read button, when i try to activate the mark all as read using my loop
let markAllAsRead = () => {
let buttons = document.getElementsByClassName("markAsRead");
let notifications = document.getElementsByClassName("notification");
let newValue = Number(counter.innerText) - 7;
if (newValue < 0) {
newValue = 0;
}
console.log(buttons);
counter.innerText = newValue;
for (let i = 0; i < notifications.length; i++) {
notifications[i].classList.remove("new");
}
for (let i = 0; i < buttons.length; i++) {
buttons[i].remove(buttons[i]);
}
};
it only will eliminate one element yes and other no like so:
live test of the function

I'm back just to update this one, the problem it self was
for (let i = 0; i < buttons.length; i++) {
buttons[i].remove(buttons[i]);
}
instead of make it look for a "default loop" I made "i" be equal to the HTMLCollection lenght, then i>= 0; --i
for (let i = buttons.length - 1; i >= 0; --i) {
buttons[i].remove();
}
making it, the function works as it should removing all the buttons of mark as read.

Related

Pushing objects back and forth between arrays results in missing objects

I have several JSON files with fake users.
They look like this:
{"name":"Beau Evans","personalityType":"yellow","skills":"JavaScript"}.
They are all pushed into an array called 'people'.
Now what I wish to do is to sort them all into subgroups into const groups = []; array.
The requirement for the groups is that they all need to share the same personalityType. (blue, yellow, red, or green) and they all need to differ in skills.
So one with HTML, JavaScript, or CSS.
And this of course resulted in some groups being of just 1 user. So I wanted to extract those back into a remainingPeople array, and then add the remainingPeople EVENLY to groups that meet the requirements so maybe 1 yellowCSS, 1 yellowJavaScript, 1 yellowHTML. It didn't matter if it turned out to be maybe 2 yellowHTML.
This is the code that I've written:
Which resulted into 2 problems.
The while loop on the bottom never stopped looping and crashed the site depending on how many JSON files with fake users I had!
And problem 2: Some users got erased out of existence so I ended up with fewer people in the groups' array than I had in the people array.
Why is this?
let homogenousGroups = [];
for (let i = 0; i < Math.floor(people.length / 3); i++) {
homogenousGroups.push([{
group: i
}]);
}
let groupsCreator = () => {
// this is to add people that has the same personality and different skills to the same group
let addPersonSameColor = (group) => {
people.sort(() => Math.random() - 0.5);
for (let j = 0; j < people.length; j++) {
let person = people[j];
let hasPersonality = group.some(groupPerson => groupPerson.personalityType === person.personalityType);
let hasSkills = group.some(groupPerson => groupPerson.skills === person.skills);
if (group.length === 0) {
group.push(person);
people.splice(j, 1);
j--;
} else if (hasPersonality && !hasSkills) {
group.push(person);
people.splice(j, 1);
j--;
}
}
};
// this runs the function above for each person in
for (let x = 0; x < homogenousGroups.length; x++) {
addPersonSameColor(homogenousGroups[x]);
}
// this will remove any object that does not have the name property
for (let x = 0; x < homogenousGroups.length; x++) {
for (let y = 0; y < homogenousGroups[x].length; y++) {
if (!homogenousGroups[x][y].name) {
homogenousGroups[x].splice(y, 1);
y--;
}
}
}
// this is to push any group that has less than 3 people back to the people array
for (let x = 0; x < homogenousGroups.length; x++) {
if (homogenousGroups[x].length <= 2) {
let removed = homogenousGroups[x].splice(0, homogenousGroups[x].length);
people2.push(...removed);
}
for (let x = 0; x < people.length; x++) {
if (people[x].group) {
people.splice(x, 1);
x--;
}
}
}
// this is to remove any empty arrays in my group array
for (let x = 0; x < homogenousGroups.length; x++) {
if (homogenousGroups[x].length === 0) {
homogenousGroups.splice(x, 1);
x--;
}
}
while (people.length > 1) {
for (let i = 0; i < homogenousGroups.length; i++) {
for (let j = 0; j < people.length; j++) {
if (people[j].personalityType === homogenousGroups[i][0].personalityType) {
homogenousGroups[i].push(people[j]);
people.splice(j, 1);
j--;
break;
}
}
}
}
};

Code blocks work separately but not together

I'm making a function for my chrome extension. It's supposed to move all tabGroups to the left most position in alphabetical order and then sort the rest of the tabs in alphabetical order aswell.
The problem is when I remove this code block everything works fine, meaning the tabGroups gets moved to the left most position. But when I add it back it stops working. The thing is that the code block works on it's own if I manually move the tabGroups myself. Any help is appreciated!
for (let i = 0; i < titles.length; i++) {
for (let j = 0; j < titles.length; j++) {
if (tabs[i + moveIndex].title == titles[j]) {
chrome.tabs.move(tabs[i + moveIndex].id, { index: (j + moveIndex) });
}
}
}
This is the full function, with tabs being: let tabs = await chrome.tabs.query({ currentWindow: true });
async function titleSort(tabs) {
// Puts groups in current window into an array
let groups = await chrome.tabGroups.query({ windowId: -1 });
console.log(groups);
// Separates titles into a different array
let groupTitles = [];
for (let i = 0; i < groups.length; i++) {
groupTitles.push(groups[i].title);
}
// Sorts the array alphabetically
groupTitles.sort((a, b) => a.localeCompare(b));
console.log(groupTitles);
// Put groups into an array in alphabetical order
let groupsAlph = [];
for (let i = 0; i < groups.length; i++) {
for (let j = 0; j < groupTitles.length; j++) {
if (groupTitles[i] == groups[j].title) {
groupsAlph.push(groups[j]);
}
}
}
console.log(groupsAlph);
chrome.storage.sync.get(["preserveGroupOrder"], (data) => {
if (data.preserveGroupOrder == false) {
// Separates titles into a different array
let titles = [];
for (let i = 0; i < tabs.length; i++) {
titles.push(tabs[i].title);
}
// Sorts the array alphabetically
titles.sort((a, b) => a.localeCompare(b));
// Checks if the titles match and rearranges the tabs accordingly
for (let i = 0; i < tabs.length; i++) {
for (let j = 0; j < titles.length; j++) {
if (tabs[i].title == titles[j]) {
chrome.tabs.move(tabs[i].id, { index: j });
}
}
}
} else if (data.preserveGroupOrder == true) {
let tabsInGroup = [];
// Resets values to 0 in tabsInGroup
for (let i = 0; i < groups.length; i++) {
tabsInGroup[i] = 0;
}
// Gets the amount of tabs in each group
for (let i = 0; i < tabs.length; i++) {
for (let j = 0; j < groups.length; j++) {
if (tabs[i].groupId == groupsAlph[j].id) {
tabsInGroup[j]++;
}
}
}
console.log(tabsInGroup);
// Moves groups to the left most positions
let moveIndex = 0;
for (let i = 0; i < groupsAlph.length; i++) {
chrome.tabGroups.move(groupsAlph[i].id, { index: moveIndex });
moveIndex += tabsInGroup[i];
}
console.log(moveIndex);
// Separates titles into a different array
let titles = [];
let tabsLength = tabs.length - moveIndex;
for (let i = 0; i < tabsLength; i++) {
titles.push(tabs[i + moveIndex].title);
}
// Sorts the array alphabetically
titles.sort((a, b) => a.localeCompare(b));
console.log(titles);
// TODO: Sort the rest of the tabs (works separately)
// Checks if the titles match and rearranges the tabs accordingly
for (let i = 0; i < titles.length; i++) {
for (let j = 0; j < titles.length; j++) {
if (tabs[i + moveIndex].title == titles[j]) {
chrome.tabs.move(tabs[i + moveIndex].id, { index: (j + moveIndex) });
}
}
}
}
});
}
I'm fairly confident that the issue is that you're not requerying tabs after you move tab groups:
chrome.tabGroups.move(groupsAlph[i].id, { index: moveIndex });
If you're only creating the tabs index once, then if tabs 6 - 8 are part of a group, and the group gets moved to index spots 0-2 by that line, your tabs variable does not know that unless you requery. So when you start resorting tabs 3 through 8, you're including tabs you don't want to and excluding tabs that you do. If for some reason you don't want to requery, you could keep track of the index numbers where you find tabs and have your title builder start at zero and skip the tabs. I.e., instead of ->
for (let i = 0; i < tabsLength; i++) {
titles.push(tabs[i + moveIndex].title); ...
Something like ->
for (let i = 0; i < tabs.length; i++) {
if (isNotGroupMember[i]) {
titles.push(tabs[i].title); ...
You would need to readjust some other pieces, but there's a good chance that will be the case regardless.
If that's not the issue, it's not clear from your code and I have a second hypothesis, but I'd try that first.
Also, it's not your question, but you may be interested in sorting arrays of objects by a key, rather than separating out the titles, sorting those, and then match sorting them back into place. See an example at w3schools. Although maybe there's a good reason to build your own sort.

Enable onclick event with JavaScript

I need to disable all buttons that match by class name and after the function runs, enable them back. I've tried the following but no luck.
let stb = document.getElementsByClassName("btn-st");
for (let i = 0; i < stb.length; i++) {
stb.onclick = null;
}
// run some additional functions and enable
stb.onclick = true;
What am I missing?
So the main two things that are missing is that the document.getElementsByClassName("btn-st"); returns an array so when you first go through and disable the .onclick you would have to do:
let stb = document.getElementsByClassName("btn-st");
for (let i = 0; i < stb.length; i++) {
stb[i].onclick = null;
}
For the second portion, a couple people have mentioned that setting .onclick = true; doesn't really make sense, so instead you should set the onclick to an unnamed function with the following:
// run some additional functions and enable
for (let i = 0; i < stb.length; i++) {
stb[i].onclick = function() {
// do things when this button is clicked
};
}
You need to loop through stb again:
let stb = document.getElementsByClassName("btn-st");
for (let i = 0; i < stb.length; i++) {
stb[i].onclick = null;
}
// run some additional functions and enable
for (let i = 0; i < stb.length; i++) {
stb[i].onclick = true;
}
Keep in mind however that setting the onclick attribute to null won't disable the event (see #Jeremy Thille's comment).
If you want to disable a button, you should instead set its disabled property:
let stb = document.getElementsByClassName("btn-st");
for (let i = 0; i < stb.length; i++) {
stb[i].disabled = true;
}
// run some additional functions and enable
for (let i = 0; i < stb.length; i++) {
stb[i].disabled = false;
}

checking data attribute in a array

I have a list of events on a page. My end goal is to hide a purchase button (by adding a class to it) if the event has passed, using JQuery/Javascript. Each event has a 3 data attributes(month, day, year). I tried using the following method to cycle through an array:
var matches = document.querySelectorAll(".event-event");
var i = 0;
for (i = 0; i < matches.length; i++) {
var event = matches[i].getElementsByClassName('date');
var eventDate = event.getAttribute('data-date');
}
But it says that "getAttribute" is not a function, I've also tried ".attr" and it said the same thing.
var matches = document.querySelectorAll(".event-event");
for (var i = 0; i < matches.length; i++) {
var event = matches[i].getElementsByClassName('date');
if (event.length > 0) {
for (var j = 0; j < event.length; j++) {
var eventDate = event[i].getAttribute('data-date');
}
}
}
The getElementsByClassName method returns an array.
Try this:
var matches = document.querySelectorAll(".event-event");
for (var i = 0; i < matches.length; i++) {
var events = matches[i].getElementsByClassName('date');
for(var j = 0; j < events.length; j++) {
var eventDate = events[j].getAttribute('data-date');
}
}
events is an array that you must iterate through.

How to rewrite loop to recursion

I implemented a search function and loop that search by collection. In first iteration I need to search by all collection, but all next iterations only by result of the first iteration. I use if-statement if (i >= 1) collection = result; to do it, but it's not safe because I need to save collection. Is it possible to rewrite loop to recursion function? How I can make it or make my code elegant?
var targets = target.split(' '); // => ['hello', 'world'];
for (var i = 0; i < targets.length; ++i) {
if (i >= 1) {
collection = result;
}
result = includes(collection, props, targets[i]);
}
My search function:
function includes(collection, props, target) {
var result = [];
var collection_length = collection.length;
var props_length = props.length;
var target_length = target.length;
for (var i = 0; i < collection_length; ++i) {
for (var j = 0; j < props_length; ++j) {
if (collection[i][props[j]]) {
if (collection[i][props[j]].toLowerCase().slice(0, target_length) === target) {
result.push(collection[i]);
continue;
}
}
}
}
return result.length !== 0 ? result : false;
}
var result = collection;
for (var i = 0; i < targets.length; ++i) {
result = includes(result, props, targets[i]);
}
Maybe I'm missing something but isn't this what you're trying to do?

Categories

Resources