I'm trying to use change the opacity of a class that is passed into the function parameter as element. It seems to crash as it reaches "target.style.opacity = newSetting"
I'm not sure what is causing this issue because when I use a getElementById instead it works.
here's the Javascript
var fade_out_from = 10;
function fadeOut(element)
{
moving = true;
var target = document.getElementsByClassName(element);
var newSetting = fade_out_from / 10;
target.style.opacity = newSetting;
fade_out_from--;
if(fade_out_from == 0){
target.style.opacity = 0;
target.style.display = "none";
clearTimeout(loopTimer);
fade_out_from = 10;
moving = false;
return false;
}
var loopTimer = setTimeout(fadeOut(element),10);
}
document.getElementsByClassName returns a list of elements (https://developer.mozilla.org/en-US/docs/Web/API/document.getElementsByClassName) that is why target.style.opacity is undefined. Instead try to use target[0].style.opacity (unless you actually need to deal with more than one found element; in that case the script will become slightly more complex).
But even then the script won't fade out the element because of the way you are using setTimeout (https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout). The first parameter there is supposed to be a callback (just a name of a function). If you want to pass parameters, you need to add them as 3rd, 4th, etc. parameters (won't work in IE<9).
So your script may look the following way:
var fade_out_from = 10;
function fadeOut(element)
{
moving = true;
var target = document.getElementsByClassName(element);
var newSetting = fade_out_from / 10;
target[0].style.opacity = newSetting;
fade_out_from--;
if(fade_out_from == 0){
target[0].style.opacity = 0;
target[0].style.display = "none";
clearTimeout(loopTimer);
fade_out_from = 10;
moving = false;
return false;
}
var loopTimer = window.setTimeout(fadeOut,10, element);
}
So this is what I came out with that seemed to do the trick. You would just have to add aditional "target[2].style.opacity = setting" to account for additional elements in the same class.
var fade_out_from = 10;
var fadeTimer = setTimeout(function fadeOut(element){
var target = document.getElementsByClassName(element);
if(fade_out_from == 0){
target[0].style.opacity = 0;
target[1].style.opacity = 0;
fade_out_from = 10;
moving = false;
clearTimeout(fadeTimer);
return false;
}
moving = true;
var newSetting = fade_out_from / 10;
target[0].style.opacity = newSetting;
target[1].style.opacity = newSetting;
fade_out_from--;
return true;
},50);
Related
for(let i = 0; i < 8; i++) {
let childDiv = document.createElement('div');
divi.id = "addDay";
childDiv.className = "boxName";
divi.appendChild(childDiv);
childDiv.textContent = "0";
}
document.querySelector('#map');
map.appendChild(divi);
divi.firstChild.style.backgroundColor = "green";
change();
}
function change(){
n = document.getElementById('addDay');
n.firstChild.textContent = 'something';
}
I need to change content of first child of addDay on every click,but this function makes it only once. What do you think where is problem?
I have been looking at this code for a long time trying to figure this out, but I am having no luck. This issue is that I want to assign a value to the parameter boxId. When I click on a box in the webpage an alert will come up displaying that id. I have tried many things, but nothing seems to work. I'm a beginner, so I feel at this point there just must be something that I don't know how to do.
constructor function:
function Box (boxId, name, color, number, coordinates) {
this.boxId = boxId;
this.name = name;
this.color = color;
this.number = number;
this.coordinates = coordinates;
}
global variables:
var boxes = [];
var counter = 0;
var boxId = 0;
init function:
window.onload = init;
function init() {
var generateButton = document.getElementById("generateButton");
generateButton.onclick = getBoxValues;
var clearButton = document.getElementById("clearButton");
clearButton.onclick = clear;
}
function to get values and create new boxes:
function getBoxValues() {
var nameInput = document.getElementById("name");
var name = nameInput.value;
var numbersArray = dataForm.elements.amount;
for (var i = 0; i < numbersArray.length; i++) {
if (numbersArray[i].checked) {
number = numbersArray[i].value;
}
}
var colorSelect = document.getElementById("color");
var colorOption = colorSelect.options[colorSelect.selectedIndex];
var color = colorOption.value;
if (name == null || name == "") {
alert("Please enter a name for your box");
return;
}
else {
var newbox = new Box(boxId, name, color, number, "coordinates");
boxes.push(newbox);
counter++;
var boxId = counter;
}
addBox(newbox);
var data = document.getElementById("dataForm");
data.reset();
}
function that adds boxes to the page:
function addBox(newbox) {
for (var i = 0; i < newbox.number; i++) {
var scene = document.getElementById("scene");
var div = document.createElement("div");
div.className += " " + "box";
div.innerHTML += newbox.name;
div.style.backgroundColor = newbox.color;
var x = Math.floor(Math.random() * (scene.offsetWidth-101));
var y = Math.floor(Math.random() * (scene.offsetHeight-101));
div.style.left = x + "px";
div.style.top = y + "px";
scene.appendChild(div);
div.onclick = display;
}
}
function to display alert when box is clicked:
function display(e) {
var a = e.target;
alert(a.counter);
}
function to clear boxes:
function clear() {
var elems = document.getElementsByClassName("box");
for ( k = elems.length - 1; k >= 0; k--) {
var parent = elems[k].parentNode;
parent.removeChild(elems[k]);
}
}
All of the other functions work just fine. I keep running into the id showing up as "undefined" when I click it, or the counter displaying "0" in the console log, for everything I've tried.
You can do it like this.
First, in addBox() embed boxId as an tag's attribute like this:
div.setAttribute('data-boxId', newbox.boxId);
Then in display() you can retrieve it back:
alert(e.target.getAttribute('data-boxId'));
Please tell if you do not prefer this approach and I will post an alternative (closure things).
Edit: Add jsfiddle example http://jsfiddle.net/runtarm/8FJpU/
One more try. Perhaps if you change:
var boxId = counter;
to
boxId = counter;
It will then use the boxId from the outer scope instead of the one defined in the function getBoxValues()
I want to be able to click on a box (the boxes are created through code, and receive values from a form) in the webpage and display information about the box. I am working on a display() function that uses an event object and an alert to display information about the box. So far, I've had multiple odd failures in my attempt to do this, which leads me to believe that I'm not accessing object attributes correctly. I'm a beginner, so this could be really obvious, but thanks for the help.
constructor function:
function Box (counter, name, color, number, coordinates) {
this.counter = counter;
this.name = name;
this.color = color;
this.number = number;
this.coordinates = coordinates;
}
Global variables:
var boxes = [];
var counter = 0;
Init function:
function init() {
var generateButton = document.getElementById("generateButton");
generateButton.onclick = getBoxValues;
var clearButton = document.getElementById("clearButton");
clearButton.onclick = clear;
}
Function that gets values from the form:
function getBoxValues() {
var nameInput = document.getElementById("name");
var name = nameInput.value;
var numbersArray = dataForm.elements.amount;
for (var i = 0; i < numbersArray.length; i++) {
if (numbersArray[i].checked) {
number = numbersArray[i].value;
}
}
var colorSelect = document.getElementById("color");
var colorOption = colorSelect.options[colorSelect.selectedIndex];
var color = colorOption.value;
if (name == null || name == "") {
alert("Please enter a name for your box");
return;
} else {
var newbox = new Box(counter, name, color, number, "coordinates");
boxes.push(newbox);
counter++;
/*for(m = 0; m < boxes.length; m++) {
counter.newbox = boxes[m];
}*/
}
addBox(newbox);
var data = document.getElementById("dataForm");
data.reset();
}
function that assigns attributes to the boxes:
function addBox(newbox) {
for (var i = 0; i < newbox.number; i++) {
var scene = document.getElementById("scene");
var div = document.createElement("div");
div.className += " " + "box";
div.innerHTML += newbox.name;
div.style.backgroundColor = newbox.color;
var x = Math.floor(Math.random() * (scene.offsetWidth-101));
var y = Math.floor(Math.random() * (scene.offsetHeight-101));
div.style.left = x + "px";
div.style.top = y + "px";
scene.appendChild(div);
div.onclick = display;
//console.log(newbox);
//shows all of the property values of newbox in the console
//console.log(div); shows that it is an object in the console
//console.log(div.hasAttribute(number)); says false
}
}
display function:
function display(e) {
// alert(e.target); says its an html object
//alert(e.target.className); works - says "box"
//alert(e.target.hasAttribute(name)); says false
}
I've included some of the things i've found in comments.
The event object only gives you the name not a reference to the element. So... a couple of things.
First if you want to be browser agnostic you want something like (e.srcElement is for IE):
var x = e.target||e.srcElement;
Then get a reference to the element and do what you want:
var refToElement = document.getElementById(x.id);
So I have a problem where the eventlisteners I setup all happen to work with the same variable.
This is how it looks like:
// Prepare tooltips
for (var i = 0; i < document.getElementsByClassName("tooltip").length; i++) {
var tooltip = document.getElementsByClassName("tooltip")[i];
var input = document.getElementsByName(tooltip.id.substr(8))[0];
var offsetTop = 0;
var tmp = input;
while (tmp != null) {
offsetTop += tmp.offsetTop;
tmp = tmp.offsetParent;
}
offsetTop -= 130;
var offsetLeft = (input.offsetParent.offsetLeft + input.scrollWidth) + 50;
tooltip.innerHTML += "<div class='corner'></div>";
tooltip.style.top = offsetTop + "px";
tooltip.style.left = offsetLeft + "px";
input.addEventListener("focus", function() { document.getElementById(tooltip.id).style.display = "block"; });
input.addEventListener("blur", function() { document.getElementById(tooltip.id).style.display = "none"; });
}
In the last two lines I set the eventlisteners.
So whenever I focus an input field, no matter which one tooltip.id is always the same.
I checked the input.id before its different in every loop.
Javascript is a funny language :)
In each loop you're declaring a function which uses a reference to the variable tooltip.
Since you use the variable many times: its value changes but the reference remains the same.
When the function executes, it uses the reference (which has the last value).
Here is the solution:
(I recommend calling the method 'document.getElementsByClassName("tooltip")' only once since it causes DOM traverse.
==== CODE STARTS HERE
var toolips = document.getElementsByClassName("tooltip");
for (var i = 0; i < toolips.length; i++)
{
var tooltip = toolips[i];
var input = document.getElementsByName(tooltip.id.substr(8))[0];
var offsetTop = 0;
var tmp = input;
while (tmp != null)
{
offsetTop += tmp.offsetTop;
tmp = tmp.offsetParent;
}
offsetTop -= 130;
var offsetLeft = (input.offsetParent.offsetLeft + input.scrollWidth) + 50;
tooltip.innerHTML += "<div class='corner'></div>";
tooltip.style.top = offsetTop + "px";
tooltip.style.left = offsetLeft + "px";
// assign tooltip id to the input
input.tooltipId = tooltip.id;
// add event listeners
input.addEventListener("focus", function() { document.getElementById(this.tooltipId ).style.display = "block"; });
input.addEventListener("blur", function() { document.getElementById(this.tooltipId).style.display = "none"; });
}
==== CODE ENDS HERE
function createObjects(element, depth){
element.label = element.getElementsByTagName("label")[0].firstChild.nodeValue;
element.url = element.getElementsByTagName("url")[0].firstChild.nodeValue;
element.depth = depth;
if(treeWidths[depth] == undefined){
treeWidths[depth] = 1;
} else {
treeWidths[depth]++;
}
element.children = new Array();
allNodes.push(element);
var children = element.getElementsByTagName("children")[0].childNodes;
for(var i=0; i<children.length; i++){
if(children[i].nodeType != 3 && children[i].tagName == "node"){
element.children.push(createObjects(children[i], depth+1));
}
}
element.expanded = false;
element.visible = false;
element.moved = false;
element.x = 0;
element.y = 0;
if (getNodeWidth() < element.label.length * 10)
element.width = element.label.length * 10;
else
element.width = getNodeWidth();
element.height = getNodeHeight();
return element; }
Having problems with Firefox, it says that 'element.children.push' is not a function but works (only) in Google Chrome...
Any clue?
element.children = new Array();
I wouldn't add an array as a property of an element. If you want to add children to an element, this is not the right way. Also if you want to just use an array to manage data, this is not the right way either.
If you want to add child elements use:
element.appendChild(createObjects(children[i], depth + 1));