jquery selecting elements and removing classes with partial class names - javascript

I have the following piece of JQuery code which searches an html document for instances of elements with the class <xyz>-annotation-invisible and replaces it with <xyz>-annotation-visible. The catch is that if a particular element already has class <abc>-annotation-visible, then I want to remove all classes of the form *-annotation-visible and *-annotation-invisible and replace them with the class multiple-annotation-visible. How can I check if a particular element already has <abc>-annotation-visible?
const urlParams = new URLSearchParams(window.location.search);
const annotationTypes = urlParams.get('annotypes').split(',');
const multipleVisibleClass = "multiple-annotation-visible";
$(document).ready(function () {
for (var i=0; i<annotationTypes.length; i++)
{
var annotype = annotationTypes[i];
var annotationVisibleClass = `${annotype}-annotation-visible`;
var annotationInvisibleClass = `${annotype}-annotation-invisible`;
var elem = $(`.${annotationInvisibleClass}`);
if (elem.hasClass(anyVisibleClass)) # not sure how to do this part
{
elem.removeClass(anyVisibleClass);
elem.addClass(multipleVisibleClass);
}
else
{
elem.addClass(annotationVisibleClass);
}
elem.removeClass(annotationInvisibleClass);
}
});

You could use is() and the attribute ends with selecor :
let elem = $("div");
console.log(elem.is("[class$='-annotation-visible']"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="<abc>-annotation-visible">test</div>

You can get the classes of the targeted elements, split the classes into array and then manipulate the array to get desired results. Try this
const urlParams = new URLSearchParams(window.location.search);
const annotationTypes = urlParams?.get('annotypes')?.split(',') ?? [];
$(document).ready(function(){
annotationTypes.forEach(annotype => {
let visible = `${annotype}-annotation-visible`;
let invisible = `${annotype}-annotation-invisible`;
let multiple = "multiple-annotation-visible";
$(`.${invisible}, .${visible}`).each(function(){
let arr = [];
$(this).attr('class').split(' ').forEach(cls => {
if(cls === invisible){
arr.push(visible);
}else if(cls === visible){
arr.push(multiple);
}else{
arr.push(cls);
}
});
$(this).attr('class', arr.join(' '));
})
})
});

Related

How to append the child to the parent without using the ID element?

I used an ID to add a new element to divTwo. I want to know how to add the p tag inside divOne and divTwo without referring to their identifier. please help.
// create Tag
const createElement = (elementName) => document.createElement(elementName);
const appendTo = (idElement, element) => document.getElementById(idElement).append(element);
const setAttribute = (eleName, attribute, valueAttribute) => eleName.setAttribute(attribute, valueAttribute);
const setText = (id, text) => document.getElementById(id).innerHTML = text;
// Tag HTML
// div one
const divOne = createElement("div");
const appendDivOne = appendTo("demo", divOne)
const setIDOne = setAttribute(divOne, "id", "divOne");
// div two
const divTwo = createElement("div");
const appendDivTwo = appendTo("demo", divTwo)
const setIDTwo = setAttribute(divTwo, "id", "divTwo");
// child div two
const divTwoChild = createElement("p");
const appendDivTwoChild = appendTo("divTwo", divTwoChild);
const setIDChildeTwo = setAttribute(divTwoChild, "id", "ChildeTwo");
const text = setText("ChildeTwo", "childe two");
<div id="demo"></div>
It seems you are trying to append to div1 which, according to your code, will be the first element in . If you want to append a P tag, you can do:
const divOneChild = createElement("p")
const appendP = appendTo(document.getElementById("demo").firstChild, divOneChild)
You can access your elements directly after creation... for example when using const divTwoChild = createElement("p");, you can use divTwoChild.append() ... there is also a function called insertAdjacentHTML(), where you can add a html code directly on given position, read about in in here. Examples below (last 3 lines):
// create Tag
const createElement = (elementName) => document.createElement(elementName);
const appendTo = (idElement, element) => document.getElementById(idElement).append(element);
const setAttribute = (eleName, attribute, valueAttribute) => eleName.setAttribute(attribute, valueAttribute);
const setText = (id, text) => document.getElementById(id).innerHTML = text;
// Tag HTML
// div one
const divOne = createElement("div");
const appendDivOne = appendTo("demo", divOne)
const setIDOne = setAttribute(divOne, "id", "divOne");
// div two
const divTwo = createElement("div");
const appendDivTwo = appendTo("demo", divTwo)
const setIDTwo = setAttribute(divTwo, "id", "divTwo");
// child div two
const divTwoChild = createElement("p");
const appendDivTwoChild = appendTo("divTwo", divTwoChild);
const setIDChildeTwo = setAttribute(divTwoChild, "id", "ChildeTwo");
divTwoChild.append("childe two"); // <-- here
divOne.append('I am div one!'); // <-- or here
divTwo.insertAdjacentHTML('beforeend', '<p>I am a new p in div 2!</p>'); // <-- or here
<div id="demo"></div>

Remove one item from an array when clicked by only js

I am new to JavaScript. I have a small code that creates list from input and then adds it to an array. I am able to remove one item from the DOM when the item is clicked, but I couldn't remove it from the array.
I tried to use array.splice(item, 1)
lists.addEventListener("click", function (e) {
e.target.closest("li").remove();
userInputArr.splice(item, 1);});
But it removes the entire array sometime, and sometime removes the last item. when I console log the code, it looks like I clicked 3 or 4 times on the list even though I just clicked once. I have no idea what's wrong. this is the entire code:
const lists = document.querySelector(".lists");
const userInput = document.querySelector(".add-note");
const addBtn = document.querySelector(".add-btn");
const item = document.querySelectorAll(".list");
userInputArr = [];
function addNote() {
if (userInput.value < 1) {
return;
}
lists.insertAdjacentHTML(
"afterbegin",
`<li class='list'>${userInput.value}</li>`
);
userInputArr.push(lists);
lists.addEventListener("click", function (e) {
e.target.closest("li").remove();
userInputArr.splice(item, 1);
});
userInput.value = "";
}
addBtn.addEventListener("click", function () {
addNote();
});
Code is totally meaningless
1)
userInputArr.push(lists)
why you push the same element all the time? As lists refers to the first and the only element with class 'lists'?
2)
userInputArr.splice(item, 1)
please watch carefully what splice does? The first argument is number, but you pass a collection of elements with class 'list'. But i camn not even suggest which element should be removed as it contains the same element as i mentioned in first point
3) You do not need this array at all
So right approach is something like this
const lists = document.querySelector(".lists");
// just once create listener, no need to do it each time
lists.addEventListener("click", function (e) {
// if you want to remove clicked item then
if (e.target.tagName === 'LI') e.target.remove();
// but if you want to remove the first one then uncomment line
// if (this.children[0]) this.children[0].remove()
});
const userInput = document.querySelector(".add-note");
const addBtn = document.querySelector(".add-btn");
///////////////////////////////////////////////////
// item is meaninglee here, so delete this line
// const item = document.querySelectorAll(".list");
//////////////////////
// array is useless too, delete this line
// userInputArr = [];
function addNote() {
// check if it is number
if (isNaN(userInput.value) || Number(userInput.value < 1)) {
return;
}
lists.insertAdjacentHTML(
"afterbegin",
`<li class='list'>${userInput.value}</li>`
);
userInput.value = "";
}
addBtn.addEventListener("click", function () {
addNote();
});
const items = (() => {
const _items = {};
let key = 0;
return {
put(value) {
_items[key++] = value;
console.log("Added", this.all());
return key - 1;
},
remove(key) {
delete _items[key++];
console.log("Removed", this.all());
},
all(asArray = true) {
return asArray ? Object.values(_items) : { ..._items
};
}
}
})();
const inputEl = document.querySelector(".input");
const itemsEl = document.querySelector(".items");
const addBtn = document.querySelector(".btn-add");
addBtn.addEventListener("click", () => {
const value = inputEl.value.trim();
if (!value.length) return;
const key = items.put(value);
const li = document.createElement("li");
li.textContent = value;
li.dataset.key = key;
itemsEl.append(li);
inputEl.value = "";
});
itemsEl.addEventListener("click", (e) => {
const li = e.target.closest("li");
items.remove(li.dataset.key);
li.remove();
});
<input type="text" class="input">
<button class="btn-add">Add</button>
<ul class="items"></ul>
Run code & View in full screen.
use shift() userInputArr.shift()
you are also getting double clicks because your addNote() function contains an event listener lists.addEventListener and it's executed by another event listner addBtn.addEventListener you should probably move
lists.addEventListener out of the addNote function

Add value for DOM nodes in list

I am trying to create a list of links using DOM nodes from the data in the database. Instead of having a link for each DOM element. The whole list only have one link. I want the link to be separate because I want to add value to it so I can identify which link the user clicks.
This is the link in HTML
This is my Javascript code in which I take data from database. I want to put each corresponding in database as the value for the corresponding link in the HTML code.
window.onload = async function outsong() {
var selected = localStorage.getItem("category")
document.getElementById("result").innerHTML = selected;
var result = [];
if(selected == "Popular") {
await db.collection("Song").doc("Popular").collection("songs").get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
result.push(doc.data());
});
});
console.log(result.length);
for(a = 0; a < result.length; a++) {
var node = document.createElement("li");
var textnode = document.createTextNode(result[a].song_name);
node.appendChild(textnode);
document.getElementById("songlist").appendChild(node);
var anchor = document.getElementById("songlist");
var att = document.createAttribute("value");
att.value = result[a].song_name;
anchor.setAttributeNode(att);
}
}
In the image, I want to separate the link, not one as the whole.
Within your loop, you'll need to create a new <a> element within each <li>, and add the song link to that a element. Modifying your code:
const songList = document.getElementById("songlist");
for(let a = 0; a < result.length; a++) {
var node = document.createElement("li");
var link = document.createElement('a');
link.setAttribute('href', result[a].song_link);
link.innerText = result[a].song_name;
node.appendChild(link);
songList.appendChild(node);
}
I don't see where you're getting the song_link from, so for the sake of the example, I guess it was in the result[a] object, alongside song_name.

How to display HTML class of current node in JS

I have variables which:
display the result (result), and
reference the current node (thisNode).
What do I need to change in my code so that it would display the HTML class?
var thisNode = document.body.firstChild;
var result = document.getElementById("resultOfButton");
result.InnerHTML = thisNode.;
/* Here, in JS are there any ways like displaying the class name,
like nodeClass */
Please give recommendations for my code. There may be some errors. Thank you.
var thisNode = document.body.firstChild;
var result = document.getElementById("resultOfButton");
var block = false;
function buttonDown()
{
if(block == true)
{
thisNode = thisNode.parentElement.firstChild;
block = false;
}
thisNode = thisNode.nextSibling;
result.innerHTML = thisNode.nodeName;
if(thisNode == thisNode.parentNode.lastChild)
{
block = true
}
}
function buttonUp()
{
// not done now...
}
function buttonEnter()
{
thisNode = thisNode.firstChild;
result.innerHTML = thisNode.c;
}
function buttonBack()
{
// not done now...
}
I think you're asking for the className attribute. I copied your first sample and added some code so you can run it on this page. You'll get the second emoji replaced by the class name of the inserted element.
var thisNode = document.getElementById("thisNode"); // document.body.firstChild;
var result = document.getElementById("resultOfButton");
result.innerHTML = thisNode.className; /*Here, in JS are there any ways like displaying the class name, like nodeClass*/
<div id="thisNode" class="sample-class">🙂</div>
<div id="resultOfButton">🙃</div>
Quoting MDN:
"The className property of the Element interface gets and sets the value of the class attribute of the specified element."

jQuery TypeError:function not found error

I want to get some properties of one of my div via following code
(function ($) {
function StickyNotes() {
this.getProperties = function (note) {
var properties = {};
properties['top'] = note.position().top;
properties['from_center'] = this.calcFromCenter(note.position().left);
properties['width'] = note.find(".resize").width();
properties['height'] = note.find(".resize").height();
return properties;
}
this.saveBoardAndNotes = function (board_id, board_name) {
var noteList = new Array();
$(".optimal-sticky-notes-sticker-note").each(function(){
// Replace plain urls with links and improve html
var note = $(this);
content = note.find(".textarea").html();
noteID = note.attr("id");
properties = JSON.stringify(this.getProperties(note));
});
}
}
var StickyNotes = new StickyNotes();
jQuery(document).ready(function (e) {
$('#sticky-notes-add-board').click(function (e) {
if(confirm('Do you want to save previous board?')) {
var board_id = $('.optimal-sticky-notes-board:last').attr('id');
var board_name = $('.optimal-sticky-notes-board:last').text();
StickyNotes.saveBoardAndNotes(board_id, board_name);
}
})
});})(jQuery);
But I get following error..
TypeError: this.getProperties is not a function
I filtered all data like content and noteID. They are showing. But problem with this.getProperties. How can i solve the problem. Thanks in advance.
Inside each loop this points to current optimal-sticky-notes-sticker-note div. One of the several ways to reference correct scope is to use variable pointing to outer this:
this.saveBoardAndNotes = function (board_id, board_name) {
var noteList = new Array();
var self = this;
$(".optimal-sticky-notes-sticker-note").each(function(){
// Replace plain urls with links and improve html
var note = $(this);
content = note.find(".textarea").html();
noteID = note.attr("id");
properties = JSON.stringify(self.getProperties(note));
});
}

Categories

Resources