I Have a .js with multiply elements inside and functions and i use it with the 'document.write' in the index.js. I want this file to reuse it as 'new .js;' as many time i need it. Is there any way to do it?
Example:
var renderer = document.createElement('div');
var bG = document.createElement('div');
var icon = document.createElement('img');
var lock = document.createElement('img');
var delete = document.createElement('button');
var txt = document.createElement('p');
var users = document.createElement('button');
var rIcon = document.createElement('img');
(function () {
renderer.id = 'Renderer';
bG.id = 'BG';
icon.id = 'icon';
lock.id = 'Lock';
delete.id = 'Delete';
txt.id = 'txt';
users.id = 'Users';
rIcon.id = 'rIcon';
renderer.appendChild(bG),
renderer.appendChild(users), renderer.appendChild(txt), renderer.appendChild(lock),
renderer.appendChild(delete), renderer.appendChild(icon),renderer.appendChild(rIcon);
document.body.appendChild(renderer);
users.addEventListener('click', OnPress);
users.addEventListener('mouseover', OnrollOver);
users.addEventListener('mouseout', OnrollOut);
delete.addEventListener('click', DeleteClick);
}());
I am trying with no hope... Do i need to make it class with constructor but if i make it, and how i will make it, how i will use it with the 'document.write' cause i need it and before the recreation?
Regards.
The first thing I can tell you about, that you must keep away from the language keywords while naming your variables and function, like the delete variable you created.
The second thing, you can do that:
function createRenderer() {
let old = document.getElementsByClassName('Renderer')
let renderer = document.createElement('div');
let bG = document.createElement('div');
let icon = document.createElement('img');
let lock = document.createElement('img');
let deleteBu = document.createElement('button');
let txt = document.createElement('p');
let users = document.createElement('button');
let rIcon = document.createElement('img');
renderer.classList.add('Renderer')
renderer.id = 'Renderer' + old.length + 1;
bG.id = 'BG' + old.length + 1;
icon.id = 'icon' + old.length + 1;
lock.id = 'Lock' + old.length + 1;
deleteBu.id = 'Delete' + old.length + 1;
txt.id = 'txt' + old.length + 1;
users.id = 'Users' + old.length + 1;
rIcon.id = 'rIcon' + old.length + 1;
renderer.append( bG, icon, lock, deleteBu, txt, users, rIcon )
users.addEventListener('click', OnPress);
users.addEventListener('mouseover', OnrollOver);
users.addEventListener('mouseout', OnrollOut);
deleteBu.addEventListener('click', DeleteClick);
return renderer
}
and now your function is just a template for your renderer div, you can call it as much as you want, and every time you have an entirely new created renderer.
then you can use this function in many many places and you can assign it to a new variable too, and these how to use the function:
document.body.append( createRenderer() ) // to append the renderer to the body
document.body.appendChild( createRenderer() ) // the same the above
anotherElement.append( createRenderer() ) // to add the renderer to another div
and you can assign a new renderer in a new variable and use it as you can:
let newRendererOne = createRenderer()
newRendererOne.append( someChildren ) // to append new children for that specific renderer
let newRendererTwo = createRenderer()
newRendererTwo.style.color = "red" // to change the bg color for that specific render.
and you can create many of it inside a loop.
I hope the idea is clear now..
Related
If you go through the process of creating html elements in JavaScript, you can see that this process is repeated a lot. For example I made a function to create, edit and delete comments in real time, please see the following code.
function addComment(comment, score) {
// Create a list for comments
const newComment = document.createElement('li');
newComment.setAttribute('data-commentid', comment._id);
newComment.classList.add('detail__comment');
// Creating a Comments Information
const commentInfo = document.createElement('div');
commentInfo.classList.add('detail__comment__info');
const scoreConfigWrap = document.createElement('div');
scoreConfigWrap.classList.add('detail__comment__score');
for (let i = 0; i < score; i++) {
const filledScore = document.createElement('i');
const filledScoreClass = ['fa-solid', 'fa-star', 'filled'];
filledScore.classList.add(...filledScoreClass);
scoreConfigWrap.appendChild(filledScore);
}
for (let j = score; j < 5; j++) {
const score = document.createElement('i');
const scoreClass = ['fa-solid', 'fa-star'];
score.classList.add(...scoreClass);
scoreConfigWrap.appendChild(score);
}
// Create a comment edit button and include it in its parent
const commentBtns = document.createElement('div');
commentBtns.classList.add('detail__comment__btns');
const modifyBtn = document.createElement('button');
modifyBtn.innerText = 'Update';
modifyBtn.classList.add('detail__comment__modify-btn');
const cancelModifyBtn = document.createElement('button');
cancelModifyBtn.innerText = 'Cancel';
cancelModifyBtn.classList.add('detail__comment__modify-cancel');
cancelModifyBtn.classList.add('hidden');
commentBtns.appendChild(modifyBtn);
commentBtns.appendChild(cancelModifyBtn);
commentInfo.appendChild(scoreConfigWrap);
commentInfo.appendChild(commentBtns);
// Create space for comment text, author
const commentText = document.createElement('div');
commentText.classList.add('detail__comment__text');
const span = document.createElement('span');
span.innerText = comment.text;
const commentOwner = document.createElement('a');
commentOwner.setAttribute('href', `users/${comment.owner._id}`);
commentOwner.innerText = comment.owner.uid;
commentText.appendChild(span);
commentText.appendChild(commentOwner);
// Create a delete comment button
const deleteBtn = document.createElement('button');
deleteBtn.innerText = 'X';
deleteBtn.classList.add('detail__comment__delete');
// Saving information to be used for comment editing and deletion functions
comment = {
text: comment.text,
_id: comment._id,
};
commentObj = {
comment,
commentBtns,
commentElement: commentText,
};
// Link all elements related to comments with their parent
newComment.appendChild(commentInfo);
newComment.appendChild(commentText);
newComment.appendChild(modifyForm);
newComment.appendChild(deleteBtn);
detailComments.prepend(newComment);
}
Doesn't it make you annoyed just by looking at it? The problem is I don't know how to refactor this iteration. I thought about making the process of creating html elements into a separate function.
export default function createHtmlTag(
element,
text,
attrObj,
className,
parentNode
) {
const newElement = document.createElement(element);
if (attrObj) {
newElement.setAttribute(attrObj.key, attrObj.value);
}
if (text) {
newElement.innerText = text;
}
if (className) {
newElement.classList.add(className);
}
parentNode.appendChild(newElement);
}
But even then, the code looked like it was less readable. So I'd like to get a little hint about the refactoring process.
I'm developing a web page of the game Mastermind, using images instead of colors.
I generate the password using Math.floor(Math.random() * 6) + 1; to generate numbers from 1 to 6, and using that function to convert a number to an image:
var sam = document.createElement("img");
sam.src = "./samwell_tarly.jpeg";
var arya = document.createElement("img");
arya.src = "./arya_stark.jpeg";
var dany = document.createElement("img");
dany.src = "./dany.jpeg";
var jon = document.createElement("img");
jon.src = "./jon.jpeg";
var ned = document.createElement("img");
ned.src = "./ned_stark.jpeg";
var tyrion = document.createElement("img");
tyrion.src = "./tyrion.jpeg";
var ocu1 = document.getElementById("oc1");
var ocu2 = document.getElementById("oc2");
var ocu3 = document.getElementById("oc3");
var ocu4 = document.getElementById("oc4");
function intToGot(x) {
if(x==1){return arya;}
if(x==2){return sam;}
if(x==3){return ned;}
if(x==4){return dany;}
if(x==5){return jon;}
if(x==6){return tyrion;}
}
and then:
const oc1=Math.floor(Math.random() * 6) + 1;
ocu1.appendChild(intToGot(oc1));
const oc2=Math.floor(Math.random() * 6) + 1;
ocu2.appendChild(intToGot(oc2));
const oc3=Math.floor(Math.random() * 6) + 1;
ocu3.appendChild(intToGot(oc3));
const oc4=Math.floor(Math.random() * 6) + 1;
ocu4.appendChild(intToGot(oc4));
Those are my divs:
<div class="maiores" id="oc1"></div>
<div class="maiores" id="oc2"></div>
<div class="maiores" id="oc3"></div>
<div class="maiores" id="oc4"></div>
The problem i am facing is that:
When the numbers generated are all different, all of the 4 random images appear correctly, with no problems at all. But, when there is repetition, for example, if the password should be [sam,sam,dany,jon], only the last one of the repeated images appear, and the others just don't appear. In that case, the first 'sam' wouldn't appear. I can't understand how am I using wrong the appendChild function, and I need help to solve that problem.
You've only made one image node for each character. It can only go in one place.
Just generate your images on the fly, instead of ahead of time.
function makeGot(fileName) {
const n = document.createElement("img");
n.src = filename;
return n;
}
function intToGot(x) {
if(x==1){return makeGot("arya_stark.jpeg");}
if(x==2){return makeGot("samwell_tarly.jpeg");}
if(x==3){return makeGot("ned_stark.jpeg");}
if(x==4){return makeGot("dany.jpeg");}
if(x==5){return makeGot("jon.jpeg");}
if(x==6){return makeGot("tyrion.jpeg");}
}
solution
Explanation
This is because if a node is already a part of a document, then you cannot use that node reference again in another part of a document. If you do then the previous nodes get removed and inserted into new location.
const parent = document.querySelector("#parent");
const parent2 = document.querySelector("#parent2");
function createListChildElement(text) {
const element = document.createElement("li");
element.textContent = text;
return element;
}
const firstListChild = createListChildElement("First");
parent.appendChild(firstListChild);
const secondListChild = createListChildElement("Second");
parent.appendChild(secondListChild);
parent2.appendChild(firstListChild);
<h1>Second List</h1>
<ul id="parent"></ul>
<h1>Second List</h1>
<ul id="parent2"></ul>
Solution
You can create a new node/clone and append it to a new parent. You can do this using cloneNode method node
const parent = document.querySelector('#parent');
const parent2 = document.querySelector('#parent2');
function createListChildElement( text ) {
const element = document.createElement('li');
element.textContent = text;
return element;
}
const firstListChild = createListChildElement("First");
parent.appendChild( firstListChild );
const secondListChild = createListChildElement("Second");
parent.appendChild( secondListChild );
const clonedChild = firstListChild.cloneNode(true);
parent2.appendChild( clonedChild );
<h1>First list</h1>
<ul id="parent"></ul>
<h1>Second list</h1>
<ul id="parent2"></ul>
My goal is to have the appendChild(detail) appear after the appendChild(image) but it doesn't show up in the browser.
document.getElementById("myBtn2").addEventListener("click", hey);
function hey(){
for (i = 1; i < radio.length; i++){
f = radio[i].image ;
var item = document.createElement('div');
item.id = "box";
item.className = "dell";
item.style.height = "140px";
detail = document.createElement('div');
detail.className = "space";
image = document.createElement('img');
image.id = "pic";
image.className = "dell3";
image.setAttribute("src", f);
document.getElementById('case').appendChild(item).appendChild(image).appendChild(detail);
}
}
appendChild() returns the appended node. It's not chainable in the way that you think. In your code, item is appended to 'case', image to item and detail to image. Since image is an <img> element that should not have children, detail is not displayed.
The solution is to append each item separately to a document fragment, then append the document fragement to case.
var frag = document.createDocumentFragment();
var item = frag.appendChild(document.createElement('div'));
item.id = "box";
item.className = "dell";
item.style.height = "140px";
var detail = frag.appendChild(document.createElement('div'));
detail.className = "space";
var image = frag.appendChild(document.createElement('img'));
image.id = "pic";
image.className = "dell3";
image.setAttribute("src", f);
document.getElementById('case').appendChild(frag);
Note you probably want var keywords on the other variable assignments too as otherwise you'll create globals for each one implicitly. I've added these to the example changes I made. There are other optimisations you might want to make too, such as not doing the document.getElementById() lookup each time you loop (you can store it as a var outside of the loop).
I got a working function, but i think it should become a lot smaller and better but i aint seeing it. can someone help me improve this function make it better:
I am making a new li-item in a unordered list. in there there is omse info in 3 divisions who get a class making them float left to eachother.
this is the code i used, its all listed out, it can probly be make a lot better, and i hope to learn to refactor my code more, so help is apriciated.
// making new li item inn <ul>
function addproduction(){
// getting info from form
var startdatum_form = document.getElementById('startdatum').value;
var uren_form = document.getElementById('uren').value;
var ordernummer_form = document.getElementById('ordernummer').value;
// new li element
var newli = document.createElement('li');
newli.setAttribute('class', 'ui-state-default');
var div1 = document.createElement('div');
div1.setAttribute('class', 'div1');
var sortableicon = document.createElement('span');
sortableicon.setAttribute('class', 'ui-icon ui-icon-arrowthick-2-n-s');
// count current li elements in UL:
var number = 0;
var ullist = document.getElementById('sortable');
for(i=0;i< ullist.childNodes.length;i++){
if(ullist.childNodes[i].nodeName=='LI'){
number++;
}
}
newli.setAttribute('id', 'p'+(number+1));
// text node (item x)
var nrText = document.createTextNode('Item ' + (number+1));
div1.appendChild(sortableicon)
div1.appendChild(nrText);
var div2 = document.createElement('div');
div2.setAttribute('class', 'div1');
var indiv1 = document.createElement('div');
indiv1.appendChild(document.createTextNode('Title'));
var indiv2 = document.createElement('div');
indiv2.appendChild(document.createTextNode('Start'));
var indiv3 = document.createElement('div');
indiv3.appendChild(document.createTextNode('End'));
var indiv4 = document.createElement('div');
indiv4.appendChild(document.createTextNode('Uren'));
div2.appendChild(indiv1);
div2.appendChild(indiv2);
div2.appendChild(indiv3);
div2.appendChild(indiv4);
var div3 = document.createElement('div');
div3.setAttribute('class', 'div3');
var indiv5 = document.createElement('div');
indiv5.appendChild(document.createTextNode(ordernummer_form));
var indiv6 = document.createElement('div');
indiv6.appendChild(document.createTextNode(startdatum_form));
var indiv7 = document.createElement('div');
indiv7.appendChild(document.createTextNode('end'));
var indiv8 = document.createElement('div');
indiv8.appendChild(document.createTextNode(uren_form));
div3.appendChild(indiv5);
div3.appendChild(indiv6);
div3.appendChild(indiv7);
div3.appendChild(indiv8);
newli.appendChild(div1);
newli.appendChild(div2);
newli.appendChild(div3);
// add new production to list
document.getElementById('sortable').appendChild(newli);
saveNewEntry( (number+1), ordernummer_form, startdatum_form, uren_form );
}
A small example which could be applied to other parts of your code as well
var startdatum_form = document.getElementById('startdatum').value;
var uren_form = document.getElementById('uren').value;
var ordernummer_form = document.getElementById('ordernummer').value;
could be
var startdatum_form = get_value('startdatum');
var uren_form = get_value('uren');
var ordernummer_form = get_value('ordernummer');
function get_value( field ) {
return document.getElementById(field).value;
}
I have written a simple script and it's job is to change a innerHTML of a random element in one section of the page. Somehow when I call the function, and set it to fire every 1 second, when innerHTML of a specific element is changed, it doesn't stay that way , it just clears itself and moves on to another element. Can anyone help me with this. Here is the code, thanks in advance.
window.onload = function() {
var box1 = document.getElementById("one");
var box2 = document.getElementById("two");
var box3 = document.getElementById("three");
var box4 = document.getElementById("four");
var box5 = document.getElementById("five");
var box6 = document.getElementById("six");
var box7 = document.getElementById("seven");
var box8 = document.getElementById("eight");
var headingArray = ["RAVE", "RUN", "PAINT"];
var iconArray = ["ion-usb", "ion-android-walk", "ion-android-color-palette"];
var paragraphArray = ["Wanna good time? <br> Check out nearest party centres","Check out running tracks", "Ckeck out painting places"];
var boxArray = [box1,box2,box3,box4,box5,box6,box7,box8];
var heading = document.createElement("h2");
var icon = document.createElement("i");
var paragraph = document.createElement("p");
function getRandomNumberForContent() {
var randomHeading = Math.round(Math.random()*2) + 0;
return randomHeading;
}
function getRandomNumberForBox() {
var randomNumber = Math.round(Math.random()*7) + 0;
return randomNumber;
}
function changeBox() {
var random = getRandomNumberForContent();
heading.innerHTML = headingArray[random];
icon.className = "icon "+iconArray[random]+" big";
paragraph.innerHTML = paragraphArray[random];
var randomNum = getRandomNumberForBox();
boxArray[randomNum].innerHTML = "";
boxArray[randomNum].appendChild(heading);
boxArray[randomNum].appendChild(icon);
boxArray[randomNum].appendChild(paragraph);
}
setInterval(changeBox,1000);
}
You are somewhat moving the element to the new div each time the function is called, because you are assigning as a child the same element, not a copy of it.
You should create the new element inside the changeBox function.
That's the answer. If you create it outside the function, they will be a unique element that you are assigning either to one div or another.
I assume that it moves to another element because you append the same elements somewhere else. You could clone the elements when you append them:
boxArray[randomNum].appendChild(heading.cloneNode(true));
boxArray[randomNum].appendChild(icon.cloneNode(true));
boxArray[randomNum].appendChild(paragraph.cloneNode(true));