I'm having trouble figuring out how to pass values from one function to another. I've created a program where I create boxes using values from a form that show up in the webpage. The values I'm talking about are property values of the boxes themselves.
Here is the function where the values are assigned to the boxes:
function addBox(newbox) {
for (var i = 0; i < newbox.number; i++) {
counter++;
var id = counter;
var scene = document.getElementById("scene");
var div = document.createElement("div");
div.value = id;
console.log(div.value);
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;
}
}
Here is the function that I'm having trouble passing the values to. I need to pass them so that I can display them in an alert box when I click on each box:
function display(e) {
alert(e.target.toSource());
}
So far when I click it, I just get an empty pair of brackets in the alert box.
I tried your example in JS Fiddle: http://jsfiddle.net/jCC6n/
I'm seeing at least two problems.
"counter" is undefined, which causes the code to fail when it first attempt to increment it. I added a variable declaration at the top of the function.
toSource is undefined. I replaced that with "outerHTML", which works in Chrome, IE and presumably other browsers.
With the above changes, this worked.
function display(e) {
alert(e.target.outerHTML);
}
function addBox(newbox) {
var counter = 0;
for (var i = 0; i < newbox.number; i++) {
counter++;
var id = counter;
var scene = document.getElementById("scene");
var div = document.createElement("div");
div.value = id;
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;
}
}
addBox({ number: 3, name: "Hello", color: '#C00' });
Be advised that event handling using onclick event handlers varies from browser to browser. It will be best to use a JavaScript framework that knows all the differences and gives you a unified way to handle events. jQuery is arguably the most used such framework.
Related
I want to select all the elements of a class. Then change that class to another class . After 0.5 seconds i want to revert the elements back to their original class. I must do this 8 times in a row. Even though my code achieves that(in a way) i can't see the color changes in the buttons . Can anyone help me ? it's a timing problem i guess. Here is the js code :
$(document).ready(function(){
$('#start').click(function(){
game();
})
function game(){
var ordine = new Array();
for(var t = 1; t <= 8; t++){
var y = 0;
for (var k = 0; k < t; k++) {
var x = Math.floor((Math.random() * 4) + 1);
ordine[y++] = x;
change1(x);
setTimeout(change2(x), 500);
}
}
}
function change1(y){
var z = 'cls' + y;
var t = 'cls' + y + 2;
$("." + z).removeClass(z).addClass(t);
}
function change2(y){
var z = 'cls' + y + 2;
var t = 'cls' + y;
$("." + z).removeClass(z).addClass(t);
}
})
Here you can find the full code(html,css and js)
http://jsfiddle.net/Cx5VK/2/
The problem is in the following line:
setTimeout(change2(x), 500);
You are calling the function change2 here, passing its return value to setTimeout.
What you actually want though is to call the change2 function after 500ms. Change your code to:
setTimeout(function() { change2(x); }, 500);
That way, you are passing an anonymous function to setTimout, which will then be executed by it after 500ms.
EDIT: I've modified your JSFiddle: http://jsfiddle.net/Cx5VK/7/ stripping out a lot of code that didn't do anything in that sample (you quite possibly need it elsewhere):
$(document).ready(function () {
$('#start').click(function () {
game();
})
function game() {
var x = Math.floor((Math.random() * 4) + 1);
change1(x);
}
function change1(y) {
var z = 'cls' + y;
var t = 'cls' + y + 2;
$("." + z).removeClass(z).addClass(t);
setTimeout(function() { change2(y); }, 500);
}
function change2(y) {
var z = 'cls' + y + 2;
var t = 'cls' + y;
$("." + z).removeClass(z).addClass(t);
game();
}
});
Now, the game function simply gets a random number and calls change1 with that number as parameter. change1 itself will set the timeout to reset the color for that square via change2. At the end of that function, the game is "restarted" by a simple call to game(), to get another random number and so on and so forth. I hope this is what you were looking for.
I'm trying to assign onmouseover - onmouseout events to an array of divs with a loop.
I created the divs through a loop as well using a function parameter createDivs(x), x being number of divs and a bunch of this.property to assign styles.
Everything is working as expected, but assigning the mouse events through a loop with the divArray.Length object.
The script is the following:
Making the divs:
containers : {
create : function(containerCount){
var cArray = [this.c1Color,this.c2Color,this.c3Color];
var aCounter = 0;
divArray = [];
for (var i = 1; i <= containerCount; i++){
var c = document.createElement("div");
c.id = ("container"+i);
c.style.width = "100%";
c.style.height = (this.height) + "px";
c.style.backgroundColor = (cArray[aCounter]);
aCounter++;
document.body.appendChild(c);
divArray.push(c);
}
}
},
Assigning the Events:
events : {
on : function () {
var z = 1;
for (var i = 0; i < divArray.length; i++){
var cont = ("container" + z);
document.getElementById(divArray[i].id).onmouseover = function(){
gala.animate.openAnimation(cont);
}
document.getElementById(divArray[i].id).onmouseout = function(){
gala.animate.shrinkAnimation(cont);
}
console.log(cont);
z++;
}
}
The console show the array sort through the number of divs as expected, and the cont variable ++ increase to assign the id. However at the end, the event listeners are only applied to the last element of the array.
Btw the cont variable is just a placeholder for a parameter that passes too the animation method so it knows what div to animate, meaning animat.openAnimation(cont) cont = div name.
Looks like you need a new scope to keep the value of the cont variable constant inside the event handlers. I replaced the cont variable as it didn't really seem neccessary
events : {
on : function () {
for (var j = 0; j < divArray.length; j++){
(function(i) {
divArray[i].onmouseover = function(){
gala.animate.openAnimation("container" + (i+1));
}
divArray[i].onmouseout = function(){
gala.animate.shrinkAnimation("container" + (i+1));
}
})(j);
}
}
In High Performance Javascript book, I read about for minimizing repaints and reflows, batch DOM changes could lead a better performance, like using:
var el = document.getElementById('mydiv');
el.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;';
instead of
var el = document.getElementById('mydiv');
el.style.borderLeft = '1px';
el.style.borderRight = '2px';
el.style.padding = '5px';
I did a test in Chrome, but the result is opposite, here is my test code:
var ie = (function(){
var undef, v = 3, div = document.createElement('div');
while (
div.innerHTML = '<!--[if gt IE '+(++v)+']><i></i><![endif]-->',
div.getElementsByTagName('i')[0]
);
return v> 4 ? v : undef;
}());
// First insert 100*100 element
var total = 100 * 100;
var round = 100 * 100;
var body = document.querySelector("body");
if (ie) {
total = round = 100 * 10;
}
var createElement = function (id) {
var div = document.createElement("div");
div.setAttribute("id", "id-" + id);
return div;
}
for (var i = 0; i <= total; i++) {
body.appendChild(createElement(i));
}
// Then change style in random
function randomFromInterval(from, to) {
return Math.floor(Math.random() * (to-from+1)+from);
}
function randomWidth() {
return randomFromInterval(0, 200) + "px";
}
function randomHeight() {
return randomFromInterval(0, 200) + "px";
}
function randomColor() {
var r = randomFromInterval(0, 255),
g = randomFromInterval(0, 255),
b = randomFromInterval(0, 255);
return "rgb(" + r + ", " + g + ", " + b + ")";
}
var time = +new Date();
for (var i = 0; i <= round; i++) {
var id = randomFromInterval(0, total);
var div = document.querySelector("#id-" + id);
// The `slower` way...but it is faster, use less time
div.style.width = randomHeight();
div.style.height = randomWidth();
div.style.backgroundColor = randomColor();
// var text = "width: " + randomWidth() + "; height: " + randomHeight() + "; background: " + randomColor() + ";"
// div.style.cssText = text;
}
console.log(+new Date() - time);
Here is my demo:
http://jsfiddle.net/9BV5E/
http://jsfiddle.net/9BV5E/1/
the first one I using .style. way, and the second one is using cssTest way;
And I also test them in IE8, the two way's time are almost the same.
So is the book wrong? Or there are other reasons?
May I ask how you are testing this?
Have you entered the test cases into, say jsperf.com a la these?
The information available roundly indicates cssText is better when setting multiple styles vs individual ones, when performing tests I cant seem to replicate the results you've noted.
I need help with this app. I want the user to choose a name, color and number. When the form is submitted, boxes of the chosen color and number are generated. More boxes can be added and the originals are not erased. Each box has random positioning and a unique id.
Here is my effort: http://jsfiddle.net/christopherpl/gnVj6/
//Invoke functions only after page has fully loaded
window.onload = init;
//Create an array that will be populated by the user generated boxes
var boxes = [];
//Create a global counter variable that keeps track of the number of
//boxes generated
var counter = 0;
//Create a Box constructor function with parameters, to create box objects
//for each box that's generated
function Box(id, name, color, x, y) {
this.id = id;
this.name = name;
this.color = color;
this.x = x;
this.y = y;
}
//Set up the onclick event handler for the generate button input
function init() {
var generateButton = document.getElementById("generateButton");
generateButton.onclick = generate;
var clearButton = document.getElementById("clearButton");
clearButton.onclick = clear;
}
//Get boxes' name from user
function generate() {
var data = document.forms.data;
var textInput = document.getElementById("name");
var name = textInput.value;
if (name == null || name == "") {
alert("Please give your Amazing Box a name");
return;
}
//Get color option from user
var colorSelect = document.getElementById("color");
var colorOption = colorSelect.options[colorSelect.selectedIndex];
var color = colorOption.value;
if (!color) {
alert("Pick a color");
return;
}
//Get number of boxes to be generated from user
var amountArray = data.elements.amount;
for (i = 0; i < amountArray.length; i++) {
if (amountArray[i].checked) {
//Create and append the new <div> element
var div = document.createElement("div");
//Randomly position each <div> element
var x = Math.floor(Math.random() * (scene.offsetWidth-101));
var y = Math.floor(Math.random() * (scene.offsetHeight-101));
//Give each <div> element a unique id
var newId = div;
newId = counter++;
id = newId;
//Add the style, including the background color selected
//by the user.
div.style.left = x + "px";
div.style.top = y + "px";
div.style.backgroundColor = color;
div.setAttribute("class", "box");
scene.appendChild(div);
div.innerHTML = "Box of " + name + "<br />(click me)";
//Create an onclick event displaying the
//details of each box generated
div.onclick = function() {
alert("You clicked on a box with id " + id +
", named Box of " + name + ", whose color is " + color +
" at position " + div.style.top + ", " + div.style.left)
}
//Form reset
data = document.getElementById("data");
data.reset();
}
}
}
//Clear the boxes from scene div
function clear() {
var sceneDivs = document.querySelectorAll("div#scene div");
for (var i = 0; i < sceneDivs.length; i++) {
var scene = document.getElementById("scene");
var cutList = document.getElementsByTagName("div")[1];
scene.removeChild(cutList);
}
}
In your code, when you do this loop:
for (i = 0; i < amountArray.length; i++) {
if (amountArray[i].checked) {
/* make the div */
}
}
You are always just making one box. What you need to do is a second loop, using the value of the radio button as the length of the loop. Something like:
var totalBoxes = 0;
for (i = 0; i < amountArray.length; i++) {
if (amountArray[i].checked) {
totalBoxes = amountArray[i].value;
}
}
for (i = 0; i < totalBoxes; i++) {
/* make the div */
}
That way you will get 5 boxes if the user checked the 5 box, and so on.
I need to maintain text box values into an array in javascript onchange event. The text box control is created dynammically in javascript function. I have used below code. But at the end the array contains current element only. Previous values are not maintaining. How can I maintain textbox value each time entered.
<script type="text/javascript" language="javascript">
function DrawTextBox(j) {
var imgElement = document.getElementById('myimage');
var imgCoord = imgElement.getBoundingClientRect();
var cl = imgCoord.left + 20;
var x = x - cl;
var y = y - imgCoord.top;
var rect = document.getElementById(j);
if (rect == null) {
rect = document.createElement("div");
rect.id = j;
var pElement = document.getElementById("imgDiv");
pElement.appendChild(rect);
}
if (w < 0) {
w = 10;
}
if (h < 0) {
h = 10;
}
var l = parseInt(document.getElementById("hright").value) + 150 + 'px';
var style = rect.style;
// style.width = w + "px";
//style.height = h + "px";
style.left = l;
style.top = document.getElementById("htop").value;
style.backgroundColor = "Transparent";
//style.borderColor = "Blue";
style.position = "absolute";
style.borderStyle = "solid";
style.borderWidth = 2 + "px";
style.zIndex = 6000;
document.getElementById(j).innerHTML = "<textarea name=\"comments\" style=\" border:0\" Title=\"Enter Comment\" id=\"T1\" value=\"EnterComment:\" onchange=\"GetText()\" ></textarea>";
//document.getElementById(i).innerHTML = "<input type=\"Textarea\"...blah blah...></input>";
return rect;
}
function GetText() {
array1.push(document.getElementById('T1').value);
alert(array1.join(', '));
}
</script>
Your question doesn´t say if/when/where array1 is declared and when DrawTextBox() is called but you can´t insert multiple elements using the same ID "T1" as it violates basic HTML rules.
Try passing a referens to the current element like this onchange="GetText(this)" and use it in your GetText() function as;
function GetText(el) {
array1.push(el.value);
alert(array1.join(', '));
}