Show an ID as a :after of a CLASS? - javascript

#fp-nav{display:none}
.submenu:after{content:"I WANT #fp-nav HERE"}
<div class="submenu"> </div>
<div id="fp-nav">01 / 52</div>
Let's say I have an ID counter that updates every section change: 01 / XX, 02 / xx and so on...
How can I keep that ID hidden from the page and let it appear as an :after of a CLASS?
Thanks!

Not sure if I got what you are trying to accomplish as epascarello says, it is unclear!
body{
counter-reset: paragraph;
}
p::before {
counter-increment: paragraph;
content: "Paragraph " counter(paragraph) ": ";
}
<p>Name</p>
<p>Last Name</p>
<p>Phone #</p>
<p>Address</p>

You can manipulate the style properties of CSS rules via the styleSheets collection:
// Get the rule's stylesheet and index
let ruleIndex = -1;
let sheet = null;
let sheetRules = null;
Array.from(document.styleSheets).some(s => Array.from(s.rules || s.cssRules).some((rule, index) => {
if (rule.selectorText == ".foo::after") {
sheet = s;
sheetRules = sheet.rules || sheet.cssRules;
ruleIndex = index;
return true;
}
}));
// Update it periodically
let id = 0;
setInterval(() => {
++id;
sheet.deleteRule(ruleIndex);
ruleIndex = sheet.insertRule('.foo::after { content: "' + id + '"; }', ruleIndex);
}, 250);
.foo::after {
content: 'foo';
}
<span class="foo"></span>
You used to be able to change a rule's style properties, but they were made read-only, so now you have to remove the old rule and add a new one.

There is a solution through Jquery , you might not be able to target pseudo class like :after but you would be able to add it in the submenu div tag
//get value from the id
var k = $('#fp-nav').text();
// remove the element
$('#fp-nav').remove();
//add the value inside submenu i just gave it a class value you can change it as per your need
$(".submenu").append( "<div class='idval'>"+k +"</div> ");

Related

Split multiple class with same name using loop

I have a multiple tag in my webpage with the same class called price. Each tag is of that form
<p class="price">Price: 45$</p>
<p class="price">Price: 32$</p>
What I need at the end is to separate the price text in a span and the price in another so that it will be like that
<p class="price"><span class='h1'>Price:</span> <span class="h2">45$</span></p>
This is what I do until now but problem is that the span is not a tag but is insert as a simple string
let price = $(".price");
for (let i = 0; i < price.length; i++) {
let priceTitle = price[i].innerText.split(":")[0];
let priceToPay = price[i].innerText.split(":")[1];
price[i].innerText = ''; //Delete content of price
$(".price")[i].append("<span class='h1'>"+ priceTitle+"</span> <span class='h2'>"+ priceToPay +"</span>");
}
}
Can you help me fix this issue and perhaps optimize the code I already do.
You've just a few syntax errors e.g. you've set priceToPay then used price_toPay in your final line of code. Also jQuery.append() method is setting your content as textContent and not HTML but just use innerHTML instead. I've added a button for you to click so you can see the before and after effects. See below
window.onload = () => {
document.getElementById('mybutton').addEventListener('click', doFormat);
}
function doFormat() {
let price = $(".price");
for (let i = 0; i < price.length; i++) {
const priceTextContentArray = price[i].innerText.split(":");
let priceTitle = priceTextContentArray[0];
let priceToPay = priceTextContentArray[1];
price[i].innerHTML =
"<span class='h1'>" +
priceTitle +
"</span> <span class='h2'>" +
priceToPay +
"</span>";
}
}
.h1 {
background-color: skyblue;
}
.h2 {
background-color: coral;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js" integrity="sha512-aVKKRRi/Q/YV+4mjoKBsE4x3H+BkegoM/em46NNlCqNTmUYADjBbeNefNxYV7giUp0VxICtqdrbqU7iVaeZNXA==" crossorigin="anonymous" referrerpolicy="no-referrer" defer></script>
<button id='mybutton'>Format</button><br>
<p class="price">Price: 45$</p>
<p class="price">Price: 32$</p>
If you want to do it "the jQuery way", to build elements from strings you must use the $ constructor:
replace:
price[i].innerText = ''; //Delete content of price
$(".price")[i].append("<span class='h1'>"+ priceTitle+"</span> <span class='h2'>"+ priceToPay +"</span>");
by:
$(price[i]).html('').append( $("<span class='h1'>"+ priceTitle +"</span> <span class='h2'>"+ priceToPay +"</span>") );
As you see in jQuery you can also chain the calls, and use the .html() or .text() dedicated functions. html is more suitable here as you want to delete all inside your element, not just the text part
Notice that I also corrected your $(".price")[i] to $(price[i]), it is safer to use the var you loop on instead of doing a new jQuery selection and assume it will have the same index as in your loop

Adding ID based on innerHTML to all elements in class

I need to write a code to add IDs to all element in one class. The IDs have to be based on innerText.
Elements look like that:
<lable class="sf-label-radio">Name1<span>Some Other Text that I do not need</span><label>
<lable class="sf-label-radio">Name2<span>Some Other Text that I do not need</span><label>
etc.
Here is my code:
<script>
addIDtoGI();
function addIDtoGI() {
let searchButtons = document.getElementsByClassName('sf-label-radio');
for(i = 0; i < searchButtons.length; i++) {
x = searchButtons[i].innerHTML;
x = x.substr(0, x.search("<")).replace(/\s+/g, '-').toLowerCase();
x = onlyEngLetters(x);
searchButtons[i].setAttribute('id',x);
}
}
function onlyEngLetters(text) {
text=text.replace("ę","e");
text=text.replace("ó","o");
text=text.replace("ą","a");
text=text.replace("ś","s");
text=text.replace("ł","l");
text=text.replace("ż","z");
text=text.replace("ź","z");
text=text.replace("ć","c");
text=text.replace("ń","n");
return text;
}
</script>
Thank You for help!
Iterate the childnodes until you get to the first textNode that isn't empty to get the text you want. Note also thaat replace() only works on first instance found and you probably want to convery to lower case to match your replacements
addIDtoGI()
function addIDtoGI(){
document.querySelectorAll('.sf-label-radio').forEach(el=>{
let txtNode = el.childNodes[0];
while(!txtNode.textContent.trim()){
txtNode = txt.nextSibling
}
el.id = onlyEngLetters(txtNode.textContent);
console.log(el.id)
});
}
function onlyEngLetters(text) {
return text.toLowerCase()
.replaceAll("ę","e")
.replaceAll("ó","o")
.replaceAll("ą","a")
.replaceAll("ś","s")
.replaceAll("ł","l")
.replaceAll("ż","z")
.replaceAll("ź","z")
.replaceAll("ć","c")
.replaceAll("ń","n")
}
<label class="sf-label-radio">Name1<span>Some Other Text that I do not need</span><label>
<label class="sf-label-radio">Name2<span>Some Other Text that I do not need</span><label>
First, you define your function but you never call it.
In your script, add the "()" to "addIDToGI;": addIGToGI();
There's also a typo on searchButtons.lenght, it should be length.
It should resolve your errors.
EDIT: Also, as someone mentionned in the comments, <lable> should be <label>.
First you must call function with () and when using for loop must use variables=>
for(let i = 0; i < searchButtons.length; i++) . length is true not lenght. and of course
let x = searchButtons[i].innerHTML;
and ...
const addIdToClassByInnerHTML = cls => {
const elements = document.querySelectorAll('.' + cls);
elements.forEach(el=>{
el.setAttribute('id', el.innerHTML);
});
}
note that do not use this function if the element contains child.
if your element contains one or more child(ren), use this:
const addIdToClassByInnerHTML = cls => {
const elements = document.querySelectorAll('.' + cls);
elements.forEach(el=>{
let html = el.innerHTML;
el.querySelectorAll('*').forEach(sub=>{
html = html.replace(sub.outerHTML, '');
});
el.setAttribute('id', html);
});
}
codepen demo
snippets
const addIdToClassByInnerHTML = cls => {
const elements = document.querySelectorAll('.' + cls);
elements.forEach(el=>{
let html = el.innerHTML;
el.querySelectorAll('*').forEach(sub=>{
html = html.replace(sub.outerHTML, '');
});
el.setAttribute('id', html);
});
}
addIdToClassByInnerHTML('sf-label-radio');
console.log(document.querySelectorAll('.sf-label-radio')[0]);
label{
display: block;
}
<label class="sf-label-radio">Name1<span>Some Other Text that I do not need</span><label>
<label class="sf-label-radio">Name2<span>Some Other Text that I do not need</span><label>

How to auto generate number in an input field?

I am creating a table with an auto numbering ID column. I want to be able to have my input text field to auto-generate an ID number(when the user starts typing into the name input field).
How do I auto-generate a number into an input field?
You could use the code below. What it does is every time you click the insert button, it adds a number to the id of the item (the number next to the text field).
This code uses document.getElementById() to modify all of the elements, and uses a variable num to incremement the id value. The part where it adds the item to the list is optional - I just added it to make it look more realistic.
var num = 1;
var input = document.getElementById('item');
var p = document.getElementById('number');
var list = document.getElementById('list');
var button = document.getElementById('insert');
button.addEventListener('click', function() {
num++;
p.innerHTML = num;
list.innerHTML += "<li>" + input.value + "</li>";
});
#item {
display: inline;
}
#number {
display: inline;
margin-right: 10px;
}
<p id='number'>1</p>
<input type='text' id='item' />
<button id='insert'>Insert</button>
<ul id='list'>
</ul>
If you have an HTML table, then you could respond to all edits, listening to the input event, and decide whether to fill a unique number (or wipe it out).
Here is a generic function you could call which takes as argument the table element that should have this feature, and the number of the column that should get these ID values.
Example:
function autoId(table, colNo) {
table.addEventListener("input", function(e) {
const tr = e.target.closest("tr");
const idInput = tr.cells[colNo].querySelector("input");
for (const input of tr.querySelectorAll("input")) {
hasData = input.value.trim() !== "" && input !== idInput;
if (hasData) break;
}
if (hasData && idInput.value.trim() === "") {
idInput.value = (Math.max(...Array.from(
table.querySelectorAll("td:nth-child(" + (colNo+1) + ") input"),
input => +input.value
).filter(v => !isNaN(v))) || 0) + 1;
} else if (!hasData && idInput.value.trim() !== "") {
idInput.value = "";
}
});
}
const table = document.querySelector("table");
// Call the function passing it the table and the column that has the ID -- that's all
autoId(table, 0);
// Let's give user the possibility to add rows, using the first data row as template
document.querySelector("#btnAddRow").addEventListener("click", () => {
table.insertAdjacentHTML("beforeend", table.rows[1].innerHTML);
});
<table>
<tr><th>ID</th><th>Name</th></tr>
<tr><td><input size="2"></td><td><input></td></tr>
</table>
<button id="btnAddRow">Add row</button>

Get the value of an input field located inside a table jquery

This is supposed to be a shopping cart inspired by jeasyui.com. I have three problems with it.
I can't get the value of the quantity when it's changed in the input box.
When I remove an item from the cart, that service must be available in its appropriate tab again.
The services get indented for each new tab. I need them to start at the beginning everytime.
This is the code I have so far:codepen.io. I'm sorry if it's messy, it's my first time working with javascript/jquery. Any help is appreciated. Thank you!
function removeProduct(el) {
var name1 = $(el).closest('tr').find('td').eq(0).text();
var price1;
for (var i = 0; i < data.length; i++) {
if (name1 == data[i][0]) {
price1 = data[i][2];
}
var className = $(el).parent().attr('class');
/**Add a new list item in item class with the class name and the service name and price in paragraphs.*/
$(el).closest('tr').remove();
}
}
function changeQuantity(el) {
var name1 = $(el).closest('tr').find('td').eq(0).text();
var quantity1 = $(el).closest('tr').find('td').eq(1).value;
var price1;
for (var i = 0; i < data.length; i++) {
data[i][1] = quantity1;
data[i][2] = price * quantity1;
if (name1 == data[i][0]) {
price1 = data[i][2];
}
}
$(el).closest('tr').find('td').eq(1).html("<input type='number' value='" + quantity1 + "' style='width:100%;'>");
$(el).closest('tr').find('td').eq(3).html(price1);
}
To get the quantity do:
$(el).closest('tr').find('td').eq(1).find('input').val();
Because you are physically removing the element from the DOM with source.remove(); you can't easily. I would suggest adding a class to the element that will hide it. And then when you remove it from the card, remove that class.
For your third issue, remove the CSS that hides the product classes and instead add this:
Remove:
.Biostatistics {
display: none;
}
.ClinicalLaboratory {
display:none;
}
.Something{
display:none;
}
Add:
.Products li {
display: none;
}
Also change your js to be like this (adding the closest('li'):
x[i].closest('li').style.display = 'none';

How to get child element by ID in JavaScript?

I have following html:
<div id="note">
<textarea id="textid" class="textclass">Text</textarea>
</div>
How can I get textarea element? I can't use document.getElementById("textid") for it
I'm doing it like this now:
var note = document.getElementById("note");
var notetext = note.querySelector('#textid');
but it doesn't work in IE(8)
How else I can do it? jQuery is ok
Thanks
If jQuery is okay, you can use find(). It's basically equivalent to the way you are doing it right now.
$('#note').find('#textid');
You can also use jQuery selectors to basically achieve the same thing:
$('#note #textid');
Using these methods to get something that already has an ID is kind of strange, but I'm supplying these assuming it's not really how you plan on using it.
On a side note, you should know ID's should be unique in your webpage. If you plan on having multiple elements with the same "ID" consider using a specific class name.
Update 2020.03.10
It's a breeze to use native JS for this:
document.querySelector('#note #textid');
If you want to first find #note then #textid you have to check the first querySelector result. If it fails to match, chaining is no longer possible :(
var parent = document.querySelector('#note');
var child = parent ? parent.querySelector('#textid') : null;
Here is a pure JavaScript solution (without jQuery)
var _Utils = function ()
{
this.findChildById = function (element, childID, isSearchInnerDescendant) // isSearchInnerDescendant <= true for search in inner childern
{
var retElement = null;
var lstChildren = isSearchInnerDescendant ? Utils.getAllDescendant(element) : element.childNodes;
for (var i = 0; i < lstChildren.length; i++)
{
if (lstChildren[i].id == childID)
{
retElement = lstChildren[i];
break;
}
}
return retElement;
}
this.getAllDescendant = function (element, lstChildrenNodes)
{
lstChildrenNodes = lstChildrenNodes ? lstChildrenNodes : [];
var lstChildren = element.childNodes;
for (var i = 0; i < lstChildren.length; i++)
{
if (lstChildren[i].nodeType == 1) // 1 is 'ELEMENT_NODE'
{
lstChildrenNodes.push(lstChildren[i]);
lstChildrenNodes = Utils.getAllDescendant(lstChildren[i], lstChildrenNodes);
}
}
return lstChildrenNodes;
}
}
var Utils = new _Utils;
Example of use:
var myDiv = document.createElement("div");
myDiv.innerHTML = "<table id='tableToolbar'>" +
"<tr>" +
"<td>" +
"<div id='divIdToSearch'>" +
"</div>" +
"</td>" +
"</tr>" +
"</table>";
var divToSearch = Utils.findChildById(myDiv, "divIdToSearch", true);
(Dwell in atom)
<div id="note">
<textarea id="textid" class="textclass">Text</textarea>
</div>
<script type="text/javascript">
var note = document.getElementById('textid').value;
alert(note);
</script>
Using jQuery
$('#note textarea');
or just
$('#textid');
$(selectedDOM).find();
function looking for all dom objects inside the selected DOM.
i.e.
<div id="mainDiv">
<p>Paragraph 1</p>
<p>Paragraph 2</p>
<div id="innerDiv">
link
<p>Paragraph 3</p>
</div>
</div>
here if you write;
$("#mainDiv").find("p");
you will get tree p elements together. On the other side,
$("#mainDiv").children("p");
Function searching in the just children DOMs of the selected DOM object. So, by this code you will get just paragraph 1 and paragraph 2. It is so beneficial to prevent browser doing unnecessary progress.

Categories

Resources