I am using JavaScript to create a Label object. This Label object should be created when an event occurs. All is working fine. But, when the same event is triggered again, this is where I am seeing a problem: "adding element with duplicate id". I have tried to destroy/delete the Label object and create it every time the event is triggered. But No Luck. Any Suggestions??
Please suggest, how to re-create the Label object with same properties again and again?
Please find the code
switch(locDetail)
{
case 'K1':
klocation = "INDIA";
//var oLocLabel1 = null;
//alert("INDIA");
//document.getElementById('LocLabelContent').innerHTML = "";
var oLocLabel1 = new sap.ui.commons.Label("LocationDetailsLabel1");
oLocLabel1.setText(klocation);
oLocLabel1.placeAt("LocLabelContent1");
//delete oLocLabel1;
//document.getElementById('LocLabelContent').innerHTML = klocation;
oLocLabel1.destroy();
break;
If we create a object with new properties (appending a counter). Will that not cause extra objects?
I'm guessing you're creating a label element, if so you can create the label with all the properties and just clone it every time you need a new one, and set the ID with an increasing counter to get unique ID's, something like :
var label = document.createElement('label'),
counter = 0;
label.innerHTML = 'some label text';
label.style.color = 'red';
someElement.addEventListener('click', function() {
var lbl = label.cloneNode(true);
lbl.id = 'label_' + (++counter);
document.body.appendChild(lbl);
}, false);
Related
I ran into a very interesting problem during use event listeners on dynamically created elements using Vanilla Javascript. I will first define the problem and later post the code.
I create dynamic html elements using javascript and during creation process I add "click" event listeners on each newly created object. And inside this event event listener I change a different property of a GLOBAL object. I mean, when you click a dynamically created element, each element modifies a different property of this global object.
Problem occurs here, I dynamically select the different property of the global object. So for each element it modifies a different property of th global object. BUT when I run the code, I see that each element only changes the latest property of the global object. Meaning that each element changes the same property of that object and it is the latest property of the object. Here the code:
var filter = {1:false, 4:false, 7:false, 11:false, 8:false} //global object
var productsAndIndexes = {a:1, b:4, c:7, d:11, e:8 } //another global object used for looping
function createEmptyFilter(){
var hdr = document.querySelector("div.content .headers");
for(var product in productsAndIndexes){
var inp = document.createElement("input");
inp.setAttribute("type", "checkbox");
var filterInd = productsAndIndexes[product];
inp.addEventListener("click" , (e) => {
if(e.target.checked){
filters[ filterInd ] = true;
}else{
filters[ filterInd ] = false;
}
});
hdr.appendChild(inp);
}
}
createEmptyFilter();
Every time I check a checkbox, I got filter = {1:false, 4:false, 7:false, 11:false, 8:true}. But instead each checkbox should modify its related part in the object.
Any explanation and solution about the problem is appreciated (although I am not 15 rep :) )
Thanks
The issue is that your filterInd variable is declared with var meaning it is function scoped, not scoped to your for loop block. That means that each loop iteration will overwrite the same variable, so the click handlers all close over that same variable, not unique variables with different values. Declare it with const or let instead, and the click handler will reference the value unique to the loop iteration.
Since you're using a browser modern enough to support =>, then you probably support let and const; there's really no good reason to ever use var nowadays.
const filter = {1:false, 4:false, 7:false, 11:false, 8:false} //global object
const productsAndIndexes = {a:1, b:4, c:7, d:11, e:8 } //another global object used for looping
function createEmptyFilter(){
const hdr = document.querySelector("div.content .headers");
for (let product in productsAndIndexes) {
const inp = document.createElement("input");
inp.setAttribute("type", "checkbox");
const filterInd = productsAndIndexes[product];
inp.addEventListener("click", e => {
if (e.target.checked) {
filters[filterInd] = true;
} else {
filters[filterInd] = false;
}
});
hdr.appendChild(inp);
}
}
createEmptyFilter();
I was wondering if it was possible to create a new variable when a button is pressed. For example: if I have a variable named enemy1 and the button is pressed, Can a variable named enemy2 be created? I'm sorry if this seems like a silly question. I wanted to create a for loop where I can define a variable thats name changes depending on 'i'.
Probably best to use an Array (adding new values on click) or Object (adding new keys on click). I think you should use an Array, so here is an example:
const enemies = [];
class Enemy {
speak () {
return 'COME AT ME BRO!!!';
}
}
document.querySelector('#createEnemy').addEventListener('click', function(event) {
const enemy = new Enemy();
enemies.push(enemy);
console.log(enemies.length, 'enemies say', enemy.speak());
}, false);
<button id="createEnemy">Create Enemy</button>
You do not require dynamic variable, instead you need one variable that would contain dynamic size (dynamic number of enemies). Following is the code you need. Here you can see demo
<button id='createEnemy' onclick='addEnenemy()'>Add Enenmy</button>
<div id='enemiesContainer'> </div>
<script>
var enemies = [];
var enemyDiv = document.getElementById('enemiesContainer');
function addEnenemy() {
var newEnenmy = 'enemy'+(enemies.length+1);
enemies.push(newEnenmy);
//following will show it in your page
enemyDiv.innerHTML = enemyDiv.innerHTML + '<br/><label>'+newEnenmy+'</label>';
console.log(enemies); //shows in console
}
</script>
I am learning extendscript for scripting adobe illustrator.It is very difficult for me to write xml related parsing.
My problem statement is given below:- "I have taken three text boxes namely name,city and country."name" is a unique key.when i click ok button the data must be saved in xml if name does not exist else update the previous name with out creating duplicate.All the names in xml file are displayed in list box.The date of particular name could be deleted by remove button.which will remove data in selected item of list box.
The code i tried to do is:-
var myWindow = new Window ("dialog", "Form");
var txt1 = myWindow.add ("edittext");//name unique
var txt2 = myWindow.add ("edittext");//city
var txt3 = myWindow.add ("edittext");//country
var btn=myWindow.add ("button", undefined, "OK");
btn.onClick = function () {
for (i=0;i<numberofnamesinxml;i++)//coding required
{
if(txt1.text!=xmlname[i]) // to verify name not there since it is like primary key
xmlFile.open("a");
xmlFile.write(root.toXMLString());
xmlFile.copy ('C:/data.xml');
xmlFile.close();
//myList refresh
}
}
var myList = myWindow.add ("listbox");
for (i=0;i<numberofnamesinxml;i++)//coding required
{
config='C:/data.xml';
config.open("r");
data= xmlname[i] //here i need to set data to
config.close();
myList.add ("item", data);
}
var btn1=myWindow.add ("button", undefined, "remove");
btn1.onClick = function () {
myList.remove (myList1.selection[i]);
//xml data having this list name must be removed
}
myWindow.show ();
Please kindly help me.
This should not be considered a full answer. I still post it because it might help finding one.
This is what I tried to write as an answer. The read/write part works but the checking of an element exists fails.
if the child is not an exact match, xml.contains(xml) will not return true.
var path = '~/Desktop/test.xml';
var xmlfile = File(path);
if (!xmlfile.exists) {
$.writeln('xml file does not exist. Creating new one');
xmlfile = new File(path);
xmlfile.open('w');
xmlfile.write('<Root></Root>');
xmlfile.close();
}
xmlfile.open('r');
xmlcontent = xmlfile.read();
xmlfile.close();
//$.writeln(xmlcontent);
var xml = new XML(xmlcontent);
// here the problems start
// the check is only working for known elements
var child = new XML('<name data="bob"></name>');
if (xml.contains(child)) {
child.#data = 'jim';
$.writeln('A child called "name" exists. Update');
xml.replace('name', child);
} else {
$.writeln('no child called "name" exists. Append');
child.#data = 'bob';
xml.appendChild(child);
}
xmlfile.open('w');
xmlfile.write(xml.toXMLString());
xmlfile.close();
My real answer is:
Use JSON instead.
I need to work with variables dynamically, and get them dynamically too. The first thing I need to know is:
How to save a variable reference(NOT its value) in a collection?
Example:
var divA = "<div>my div A</div>";
var divB = "<div>my div B</div>";
var divC = "<div>my div C</div>";
Then, save in a collection:
var mySet = new Set();
function returnDivA(){
return divA;
}
function returnDivB(){
return divB;
}
function returnDivC(){
return divC;
}
mySet.add(returnDivA());//I would like save the varible ref in a collection.
mySet.add(returnDivB());
mySet.add(returnDivC());
I want the Set collection to save the variables(NOT its values), it means:
var mySet = new Set(divA, divB, divC);
Then, with that, my intent is to do something like that:
var totalOfDivs;
for(var i = 0; i < mySet.size; i++){
totalOfDivs += mySet[i];
}
$("#anotherDIV_to_show_all_divs").html(totalOfDivs);//Then, here, I want to show all divs in the screen.
I would like suggestions, please!
It solved my problem to put variable dynamically in html using this in a for loop:
$("#anotherDIV_to_show_all_divs").append(mySet[i]);
About saving javascript variable reference in a Collection, I understand that I can't do that, because of the answer of the adeneo in comment:
"There is no "reference", all variables are pass-by-value in javascript..."
Read the documentation about set.
enter link description here
I guess you have to loop your set like this.
var totalOfDivs= "";
for (let item of mySet.values()) {
totalOfDivs+= item;
//console.log(item);
}
$("#anotherDIV_to_show_all_divs").html(totalOfDivs);
How to relate or associate an object in JavaScript to an HTML element?
For each object in an array, I generate a checkbox input element based on that object.
If I add an event listener to capture the checkbox changes, how do I retrieve the object associated with that element?
As other answers point out, generating a unique id for each DOM node allows you to use those as keys in an Object.
Another possibility is that many frameworks provide utilities for assigning data to DOM elements. For example, in jQuery you can do it by writing $(checkbox).data('mydata', obj) or in YUI Y.one(checkbox).setData('mydata', obj).
You can generate an ID for each of the checkboxes, and store the ID in the corresponding object. Then, in the event handler, you can get the ID of the changed checkbox and find the appropriate object based on that by iterating over the array.
To make it even easier to find the object, you can also map the IDs to objects (e.g. objectsByID[someID] = someObject). With this approach, you don't even have to iterate over the array.
Example of how to create the objectsByID map:
var objectsByID = {};
for (var i = 0; i < objects.length; i++) {
var id = "checkbox_" + i;
var checkbox = document.createElement("input");
checkbox.setAttribute("type", "checkbox");
checkbox.setAttribute("id", id);
// ...
objectsByID[id] = objects[i];
}
You give a progressive ID to each checkbox, starting from "checkbox0", and when you click on a checkbox you check the relative ID number, which correspond to the object in array[x].
Here is a really simple example.
Create a global object, store additional objects when you're creating the checkboxes, identified by a unique name. Set the name or id attribute of the checkbox element to this unique name.
var source = [];
var data = []; //Your data
var appendTo = document.body;//Anywhere
for(var i=0; i<data.length;i++){
var identifier = "chk"+i;
var inp = document.createElement("input");
inp.type = "checkbox";
inp.name = identifier;//.name or .id - it's up to your preference
inp.addEventListener("change", function(ev){
if(this.checked){
callback(source[this.name]);//calls function callback, passing the original object as an argument.
}
}, true);
appendTo.appendChild(inp);
source[identifier] = ...//your object.
}