update document.getElementById for same id name in different div - javascript

I know the problem here is because they both share the same id for input and for div. is there a way to specify the id of the specific div clicked like "this". without having multiple ids in my code
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script>
$(document).ready(function() {
$(this).on("click", ".descrip", function() {
$(this).next('.def').slideToggle("slow");
});
});
function addDef() {
//window.alert (1);
var def = document.getElementById("defInput").value;
//window.alert (def);
document.getElementById("addf").innerHTML += "<div class= 'descrip'> descrip </div>";
document.getElementById("addf").innerHTML += "<div class= 'def'> " + def + " </div>";
}
</script>
</head>
<body>
<div class="descrip"></div>
<div class="def"></div>
enter def for apple:
<input type="text" id="defInput">
<br>
<br>
<button onclick="addDef()">ADD</button>
<div id="addf"></div>
<div class="descrip"></div>
<div class="def"></div>
enter def for orange:
<input type="text" id="defInput">
<br>
<br>
<button onclick="addDef()">ADD</button>
<div id="addf"></div>
</body>
</html>

The value must be unique amongst all the IDs in the element’s home subtree and must contain at least one character.
W3C HTML 5.1 topic 3.2.5.1. The id attribute

Could you use class names rather than an id, then use document.getElementsByClassName instead?
<button onclick="addDef('addf-1')">ADD</button>
<div class="addf-1"></div>
<div class="descrip"></div>
<div class="def"></div>
enter def for orange:
<input type="text" id="defInput">
<br>
<br>
<button onclick="addDef('addf-2')">ADD</button>
<div class="addf-2"></div>
Then in your function:
function addDef(className) {
//window.alert (1);
var def = document.getElementById("defInput").value;
//window.alert (def);
document.getElementsByClassName(className)[0].innerHTML += "<div class= 'descrip'> descrip </div>";
document.getElementsByClassName(className)[0].innerHTML += "<div class= 'def'> " + def + " </div>";
}
NOTE: I am not advocating this method, but this is a simple fix to your issue. I am making the assumption you were not aware of the existence of any other way to retrieve a node in the DOM besides getElementById.

Directly from HTML5 Spec:
The id attribute specifies its element's unique identifier (ID). The value must be unique amongst all the IDs in the element's home subtree and must contain at least one character. The value must not contain any space characters.
An element's unique identifier can be used for a variety of purposes, most notably as a way to link to specific parts of a document using fragment identifiers, as a way to target an element when scripting, and as a way to style a specific element from CSS.
A possible solution is to change it to a class and then use the following nomenclature to target in your CSS or JS:
[class^="defInput-"], [class*=" defInput-"] {}
This will target any class that begins with defInput-

Related

How to add text to paragraphs on clicking button

I'm making a policy generator page. Where you input the text and get the output. But I'm facing the problem:
problem (I'm not able to generate multiple codes. Mean I want to generate privacy policy terms and conditions in different div areas eg:( <p id="p2"><code class="generator__markup-generated"></code></p>))
Here's my code
const generate = document.querySelector('.generate-markup');
generate.addEventListener('click', () => {
const varName = document.querySelector('#company').value;
const idName = document.querySelector('#url').value;
const markupContainer = document.querySelector('.generator__markup-generated');
//sample paragraph policy
const markup = `
${varName} have a website ${idName} which you can use to generate policies.
`;
markupContainer.textContent = markup;
});
function copyToClipboard(element) {
var $temp = $("<input>");
$("body").append($temp);
$temp.val($(element).text()).select();
document.execCommand("copy");
$temp.remove();
}
<div class="generator__markup" style="font-size: 18px; text-align: center;"><label>Company Name:</label> <input id="company" type="text" /> </div>
<div class="generator__markup" style="font-size: 18px; text-align: center;"><label>Website Url:</label> <input id="url" type="text" /> </div>
<button class="generate-markup">Generate Code</button>
</br>
<div class="generator__markup">
<h1 style="text-align: center;">Copy Your Page</h1>
<p id="p2"><code class="generator__markup-generated"></code></p>
<center>
<button onclick="copyToClipboard('#p2')">Click To Copy</button></center>
please help in this thing
To modify HTML elements, you use the JavaScript DOM API.
It appears that the text for the policies is stored in the markup variable. We need to take this text and put it inside the element as innerText.
First, we need to get a reference to the DOM element. I see that you have selected the element using querySelector to grab a class attribute. This selects all elements with that class. You need to use an id attribute instead to select a single element. Let's assume you assign the id attribute of the paragraph to generated-markup-paragraph.
So, with this corrected code, we can now set the text of the paragraph:
const markupParagraph = document.getElementById("generated-markup-paragraph");
markupParagraph.innerText = markup;
That code should go in the place of the markupContainer.textContent = markup line.

Change Class Content to href

<div class="container">
<span class="text1">test</span>
<span class="text2">test</span>
</div>
I want to change "text2" to a href in a javascript inside my function like this:
var x=document.getElementsByClassName("text2"); // Find the elements
x.innerHTML="<a href='https://test.com'>test</a>"; // Change the content
so the content of "text2" changes to a hyperlink called "test" which refers to "https://test.com"
you can do it like so:
var element = document.querySelector(".text2"); // Find the first element with the class text2
element.innerHTML = "test"; // Change the content including all HTML elements that might be in there to the value specified escaping the " character
<div class="container">
<span class="text1">test</span>
<span class="text2">test</span>
</div>
the problem was you didn't escaped the " character
you can do it also without the escaping like that:
var element = document.querySelector(".text2"); // Find the first element with the class text2
element.innerHTML = "<a href='https://test.com'>test</a>"; // Change the content including all HTML elements that might be in there to the value specified
<div class="container">
<span class="text1">test</span>
<span class="text2">test</span>
</div>
Not quite sure which approach you need. So here are both:
HTML
<div class="container">
<span class="text1">test</span>
<span class="text2">test</span>
</div>
Approach A - Replace the inner html of the target
document.querySelector(".text2").innerHTML = "<a href='https://test.com'>test</a>";
Approach B - Replace the Span with Anchor
var target = document.querySelector(".text2");
if (target) {
var anchor = document.createElement("a");
anchor.setAttribute("href", "https://www.test.com");
anchor.innerHTML = target.innerHTML;
target.replaceWith(anchor);
}

How to Write a Function that Lists Products in a Table Side-by-Side

I have a script that allows users on my e-commerce site to select 3 products and it highlights the products as they select.
How can I grab the $pro_image, title, desc, etc. of the 3 products selected and put them into a table for side-by-side view?
I am assuming we will somehow need to check for the $pro_id that is selected to identify each product separately?
<div class="col-md-10">
<h4>Not sure which product to choose? <br> Select up to 3 and compare side-by-side.</h4>
<div class="col-md-2">
<button type="compare" class="btn btn-success" name="submit-compare">Compare</button>
</div>
<div class="col-md-12">
<?php getpcatpro();
$get_products = "SELECT * FROM products ORDER BY RAND() LIMIT 0,9";
$run_products = mysqli_query($con,$get_products);
while($row_products=mysqli_fetch_array($run_products)){
$pro_id = $row_products['product_id'];
$pro_title = $row_products['product_title'];
$pro_img1 = $row_products['product_img1'];
$pro_link = $row_products['product_link'];
echo "
<div class='col-md-4 col-sm-6'>
<div class='product' onclick='highlight(this)'>
<center>
<img class='img-responsive' src='admin_area/product_images/$pro_img1'>
</center>
<div class='text'>
<center>
<a href='$pro_link'> $pro_title </a>
</center>
</div>
</div>
</div> ";
}
?>
<script>
var selected_items = 0;
function highlight(target) {
if(target.style.border == ""){
if(selected_items < 3){
target.style.border = "1px solid red";
selected_items += 1;
}
} else{
target.style.border = "";
selected_items -= 1;
}
}
</script>
</div>
</div>
Firstly, there's no button type called 'compare', please stick to standards, you shouldn't put random things into these attributes, you can create your own if need be (which I do not think you need to). See here for the three types you are allowed: https://www.w3schools.com/tags/att_button_type.asp (you should just use 'button')
Second, do not add styles through JS, you will cause an entire repaint every time you change a pixel. Instead, toggle class names on the class attribute of an element, let CSS do the work of styling, and JS do the work of interaction.
Thirdly, move all 'PHP' to the top of your script (such as defining your SQL statement and fetching the result of it) rather than having these things interspersed within HTML (just use PHP later in the document to build HTML from the PHP variables at the top of the script), such as looping through your result set to build out the HTML, not to perform important tasks such fetching the data itself, this will help you track whats doing what where so you don't tie yourself up in IF statements etc.
OK, Create a function, bound to your compare button, that toggles the state of an element. Instead of 'highlighting' using styles, toggle a class 'compare' on the product parent container:
<style>
.product.compare{
border: 1px solid red;
}
</style>
<script>
$('.btn.compare').click(function(){
$(this).closest('.product').toggleClass('compare');
});
</script>
<div class='products'>
<div class='product' data-id='1'>
<h2>A Product</h2>
<button class='btn compare'>compare</button>
</div>
<div class='product' data-id='2'>
<h2>Another Product</h2>
<button class='btn compare'>compare</button>
</div>
</div>
This will basically, when the button is clicked, find the parent element with class '.product' then toggle the class '.compare' on it, so you should have .product.compare
You'll need to design your table to have fixed rows with class names, like so:
<table class='comparison'>
<thead>
<tr class='product-title'></tr>
</thead>
<tbody>
<tr class='product-price'></tr>
</tbody>
</table>
Once you have products with a toggled state (a class has been added which both highlights the row with CSS visibly, but also flags it for comparison to jQuery, create a new button and method for it to call to build the comparison table
<button class='btn goCompare'>Go Compare</button>
$(function(){
$(".btn.goCompare").on('click', function(e){
e.preventDefault();
buildComparisonTable();
});
});
function buildComparisonTable(){
var comparisonTableBody = $('table.comparison tbody');
var comparisonTableBodyProductTitleCol = $('table.comparison thead tr.product-title');
var comparisonTableBodyProductPriceCol = $('table.comparison tbody tr.product-price');
comparisonTableBody.find('.product-col').remove();
$('.product.compare').each(function(){
var id = $(this).attr('data-id');
var title = $(this).attr('data-title');
var price = $(this).attr('data-price');
comparisonTableBodyProductTitleCol.append('<th class="product-col">'+title+'</th>');
comparisonTableBodyProductPriceCol.append('<td class="product-col">'+price+'</td>');
});
}
The choice is yours, but think about how you can cleverly and correctly mark up your pages to be easily read by your scripts. You can either stuff all of the product data into attributes on a parent element:
<div class='product' data-id='1' data-title='A Product' data-price='$10.00' data-primary-category='Homeware'>
<h2>A Product</h2>
<button class='btn compare'>compare</button>
</div>
Or you can add a class to each element that has the data you intend to gleam:
<div class='product' data-id='1'>
<h2 class='product-title'>A Product</h2>
<span class='product-price'>$10.00</span>
<span class='product-category'>Homeware</span>
<img class='product-img' src='/images/product-1.jpg' />
</div>
Now you can target what you want easily and get information from it using proper class names, a considered layout, correct use of technologies and a simple approach. This code-pen illustrates: https://codepen.io/anon/pen/voBKgV

Javascript - Repeated use of a function without it removing previous instances?

How would I repeat the output of a function, without it affecting previous instances outputs of the function?
For some context:
I am creating a text editor and have created a "link-maker" which creates an relative href link.
However, when I append the link to the text area content, the link displays perfectly for the first instance. Yet, if I repeat that function to add another relative link, it removes the html wrapping the first link appended.
I have tried changing the text output of the link to getElementByClassName, as I thought that the ID would only be best used for a sole function which would not need to be repeated. Where as by using the class it allows for more general use.
Some code for example:
<textarea name="textarea" class="txtarea" id="textarea" style="display: none; font-family: Arial;"></textarea>
<iframe name="editor" id="editor" style="width:824; height: 400; font-family: Arial;"></iframe>
function bcmllink() {
var logicalid = document.getElementById("logicalid");
var txtinput = document.getElementById("txtinput");
var txtOutput = document.getElementById("txtOutput");
var name = logicalid.value;
txtOutput.value = "\x3ca href\x3d\x22\x23\x22 bcmltype\x3d\x22link\x22 logicalid\x3d\x22" + logicalid.value + "\x22\x3e" + txtinput.value + "\x3c\x2fa\x3e"
}
function appendtotext() {
var myTextArea = $('.txtarea');
myTextArea.val(editor.document.getElementsByTagName('body')[0].innerHTML = editor.document.getElementsByTagName('body')[0].
textContent + txtOutput.value + " ")
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<textarea name="textarea" class="txtarea" id="textarea" style="display: none; font-family: Arial;"></textarea>
<iframe name="editor" id="editor" style="width:824; height: 400; font-family: Arial;"></iframe>
<div id="bcml">
<h3>BCML Links</h3>
<form action="">
<fieldset class="bcml_links">
<label>Enter your logical id</label><input type="number" id="logicalid" class="left5"/><br><br>
<label>Enter your text</label><input type="text" id="txtinput" class="left5"/><input class="left5" type="button" value="Generate" onClick="bcmllink()" /><br><br>
<input type="text" style="width : 600;" id="txtOutput" /><br><br>
<b>Copy and paste this text into your source view</b>
<input type="button" value="append" onClick="appendtotext()"/>
</fieldset>
</form>
Maybe you should consider using lists instead of textarea. Im currently using this for a chatapp im creating and it doesnt remove the previous messages when i recieve a new one.
You are already importing jquery. Why not make use of its .text() function?
$('textarea#textarea').text("<a href='ok'>Click here</a>");
Note, that you will not have to worry about formatting HTML or escaping characters.
If you want to append to a previously filled textarea: you would do something like:
var old_text = $('textarea#textarea').text();
$('textarea#textarea').text(old_text + "<a href='ok'>Click here</a>");
I managed to find the answer to what I was looking for:
function appendtotext() {
var myTextArea = $('.txtarea');myTextArea.val(editor.document.getElementsByTagName('body')[0].innerHTML = editor.document.getElementsByTagName('body')[0].
innerHTML + txtOutput.value + " ")}
The issue was that I was previously using textContent on the last line (where innerHTML now sits). This meant that with each instance of the function being used, it was removing the surrounding html tags and placing in only the text content.
See here for further information:
https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent

Citing a text area?

I'm just getting started in programming and somehow can't come up with any sensible approach to the following problem, so any help would be greatly appreciated! I have a .html file structured like this:
<head>
<title>ABC</title>
</head>
<body>
<div class="norm">
...
<span class="jnenbez">13</span>
....
<div class="Absatz">text</div>
<div class="Absatz">text</div>
<div class="Absatz">CITE HERE**</div>
The "norm" div is the one parent node. The "jnenbez" span and the "Absatz" divs are inside the "norm" div, but how deeply they are nested can vary. Now I want to cite the "CITE HERE" area, meaning to generate the output of "jnenbez 13 Absatz 3 ABC" - meaning getting the text content of the "jnenbez" span of the same "norm" div, getting the index number of the "Absatz" div, since it is the third child "Absatz" of the "norm" div and getting the content.
1) How could I give this string to the user, so he could copy paste it somewhere else? It seems it is not easily possible to modify the copy+paste behavior of Firefox. An obvious solution would be to put the output in brackets like [jnenbez...] at the end of each divs text content, but that would reduce readability of the html...
2) Is it even possible to automatically generate this output via JQuery?
Not sure about a good way to store/display the info.
Also, unsure of what other mark-up you would have in the class='norm' container. This is vitally important and impacts entirely the shape of the useful solution.
I've assumed a particular structure - one that says the first contained span is one of interest. Another assumption is that the only divs in the container are of interest and need to be counted.
I'm sure you can break it easily enough. :D
<!DOCTYPE html>
<html>
<head>
<script>
function onBtnPress(element)
{
var result;
var cont = element.parentNode;
var span = cont.getElementsByTagName('span')[0];
result = span.className + " ";
result += span.innerHTML + " ";
var divList = cont.getElementsByTagName('div');
result += divList[0].className + " ";
result += divList.length+" ";
result += document.title;
cont.getElementsByTagName('p')[0].innerHTML = result;
}
</script>
<title>ABC</title>
</head>
<body>
<div class="norm">
<span class="jnenbez">13</span>
<div class="Absatz">text</div>
<div class="Absatz">text</div>
<div class="Absatz">CITE HERE**</div>
<button onclick='onBtnPress(this);'>click me</button>
<p>[string here]</p>
</div>
<div class="norm">
<span class="Crapple">8</span>
<div class="ipod">worst</div>
<div class="ipod">music</div>
<div class="ipod">player</div>
<div class="ipod">I ever</div>
<div class="ipod">bought</div>
<div class="ipod">CITE HERE**</div>
<button onclick='onBtnPress(this);'>click me</button>
<p>[string here]</p>
</div>
</body>
</html>

Categories

Resources