how to get the actual box bigger than the others? - javascript

i'm new to javascript and i'm having a problem. I want the actual (function updateBoxes) box [boxIx] to be bigger than the other ones but i can't seem to find a code that works. i've tried box[boxIx].size ="100px"; box[boxIx].style.size ="100px"; without result. This is my code;
function init() {
box = document.getElementById("boxes").getElementsByTagName("div");
for (var i=0; i<box.length; i++) {
box[i].style.left = 70*i+"px";
} // End for
boxIx = box.length - 8;
updateBoxes();
} // End init
function browseLeft() {
if (boxIx > 0) boxIx = boxIx - 1;
updateBoxes();
}
// End browseLeft
function browseRight() {
if (boxIx < box.length-1) boxIx = boxIx + 1;
updateBoxes();}
// End browseRight
**function updateBoxes() {
box[boxIx].style.backgroundColor ="#CCC";
box[boxIx].style.top = "20px";
box[boxIx].style.zIndex = 9;**
var z = 8;
for (var i=boxIx-1; i>=0; i--) {
box[i].style.backgroundColor ="#666";
box[i].style.top = "0px";
box[i].style.zIndex = z;
z = z - 1;
} // End for
z = 8;
for (var i=boxIx+1; i<box.length; i++) {
box[i].style.backgroundColor = "#666";
box[i].style.top = "0px";
box[i].style.zIndex = z;
z = z - 1;
} // End for
} // End browseLeft

As thirtydot pointed out, you have two instances of "**" in your sample code that I've removed in the assumption that this is a markdown glitch when editing.
Your example shows only the JavaScript code. The HTML markup and CSS styling you're using would be most helpful. I've created a fiddle for discussion and to resolve this for you here: http://jsfiddle.net/bhofmann/zkZMD/
A few things I noticed that might be helpful:
You're using a magic number 8 in a few places. Can we assume this is the number of boxes? I would store that in a variable for use in the functions.
You used a lot of direct styling. Your code might be cleaner if you used CSS classes to alter the appearance of the boxes.
Unless you're altering the default styling of DIV, you won't see much change by simply setting the left offset.
PS. I took the liberty of invoking the init function on page load because I saw nothing else to invoke it. I don't know what would invoke browseLeft and browseRight but I'll leave that to you.

Related

JS increase index number array by function

I trying to make a small text based rpg game, but I came across array in js and then I came to problems, I failing to increase the index number by using i instead of 0 like myArray[i]
I made a jsfiddle so you guys can see what I mean.
jsfiddle
When you press the button til you get a warming, it should increase the i to 2, but it don't, but still comes with warming and increasing the attack variable.
This is your attackUp function:
function attackUp(){
var i = 0;
var attackCost = xpforlevel[i];
if (attackCost < attackxp) {
alert("WARMING!");
attack++;
document.getElementById('attack').innerHTML = attack;
i++;
document.getElementById('i').innerHTML = i;
}
}
Notice that your var i = 0 statement doesn't really make sense (because everytime attackUp is called, i will be reset to = 0 at the beginning). To fix that, erase this var i = 0 statement from your function and put in the beginning of your JS code:
var i = 0;
var attackxp = 0;
var attack = 1;
Further, your function will only update i if attackCost < attackxp, otherwise it will change nothing. You need to put the i++; statement outside your if-block, like this:
function attackUp(){
//erase this line: var i = 0;
var attackCost = xpforlevel[i];
i++; //added this line
if (attackCost < attackxp) {
alert("WARMING!");
attack++;
document.getElementById('attack').innerHTML = attack;
//erase this line: i++;
document.getElementById('i').innerHTML = i;
}
}
As your i is a local variable, it is initiated as 0 every time you call attackUp(). You should put it besides attackxp and attack.
For more information about the scope of variable in JavaScript, see w3schools or this question.

Making a delay in Javascript [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
I am working on a WordPress plugin. One of its features involves hiding and revealing segments of text by class using <span>.
This functionality works, but I have been hoping to enhance it by having the segments of text reveal one letter at a time (quickly of course) as though they were being typed out very quickly, rather than all at once in large chunks.
I know there are animations out there for this kind of thing ... and perhaps that would be a better solution, but I've been trying to keep it. But the functionality is not really graphic or "animation" oriented; my intent is more just to make a text-based feature look prettier.
I've gotten the portion of the code that builds each segment of text character by character, but I'm trying to insert a very short (5-10ms) delay between each character so that the effect is actually visible. I simply cannot get the setTimeout function to work; can anyone please give me some suggestions?
For simplicity I'm just including the segment of the text that does this; let me know if more context is needed. The following is the FOR loop that goes through every element of an array called cols[] and reveals each element in the array by character. This code works but the delay is never observed.
numberofSnippets = the size of the array cols[]
for (c = 0; c < numberofSnippets; c++)
{
h=0;
currentshown = '';
snippet = cols[c].textContent;
sniplength = snippet.length;
(function addNextCharacter()
{
onecharacter = snippet.charAt(h);
currentshown = currentshown.concat(onecharacter);
cols[c].textContent = currentshown;
h=h+1;
if (h < sniplength) {window.setTimeout(addNextCharacter, 200); }
})();*/
}
}
}
There were a few oddities in your code that was preventing the setTimeout from performing as expected, mostly due to the closure reusing variables within the loop due to the fact that the loop isn't going to wait for the IIFE to finish recursively executing with a setTimeout. I solved that by moving those variables to parameters passed to addNextCharacter.
var cols = document.getElementsByClassName('foo');
var numberofSnippets = cols.length;
for (var c = 0; c < numberofSnippets; c++) {
(function addNextCharacter(h, c, snippet, sniplength, currentshown) {
var onecharacter = snippet.charAt(h);
currentshown = currentshown.concat(onecharacter);
cols[c].textContent = currentshown;
h = h + 1;
if (h < sniplength) {
setTimeout(function () {
addNextCharacter(h, c, snippet, sniplength, currentshown);
}, 10);
}
})(0, c, cols[c].textContent, cols[c].textContent.length, '');
}
<div class="foo">Apple</div>
<div class="foo">Banana</div>
<div class="foo">Orange</div>
<p class="foo">There were a few oddities in your code that was preventing the setTimeout from performing as expected, mostly due to the closure reusing variables within the loop due to the fact that the loop isn't going to wait for the IIFE to finish recursively executing with a setTimeout. I solved that by moving those variables to parameters passed to addNextCharacter.</p>
And here's the obligatory .forEach version which avoids needing to pass the variables around as parameters.
var cols = document.getElementsByClassName('foo');
var numberofSnippets = cols.length;
[].forEach.call(cols, function(el) {
var snippet = el.textContent;
var sniplength = snippet.length;
var currentshown = '';
(function addNextCharacter(h) {
var onecharacter = snippet.charAt(h);
currentshown = currentshown.concat(onecharacter);
el.textContent = currentshown;
h = h + 1;
if (h < sniplength) {
setTimeout(function() {
addNextCharacter(h);
}, 1000);
}
})(0);
});
Well, one issue is that you're setting your timeout to 0, which means, effectively 'next tick'. If you want a 5 second delay, for example, you need to put 5000 in there as the second param.

new offsetHeight does not calculated after updating font size

I have a problem regarding 'offsetHeight' property does not get updated after updating font size. Bellow is the code.
function shrink_toolbar_text()
{
var toolbar = document.getElementById("toolbar");
var icons = document.getElementsByClassName("icon-alone");
var icon_size = 64;
var icon_height = icons[0].offsetHeight ;
while( icon_height > toolbar.offsetHeight)
{
// textSpan.style.fontSize = parseInt(textSpan.style.fontSize) - 1;
icon_size = icon_size -1;
for ( i=0; i< icons.length ;i++){
icons[i].style.fontSize = icon_size ;
}
icon_height = icons[0].offsetHeight ;
console.log( icon_height);
console.log( icon_size);
// console.log( parseInt(icon_size));
}
console.log("shrink_toolbar_text() ");
}
any workaround on this situation ?
I've tried following things so far.
1. Try to redraw each and every icons using show and hide.
2. Tried 'getComputedStyle()' but it don't return a value called 'offsetHeight' at all.
Any idea why code is not working?
The code should be corrected to this.
var icon_size = 64px;
and
icons[i].style.fontSize = icon_size+"px" ;
In some browsers, this code won't work without postfix 'px'. Neither it emit a error message on console. So careful coding on this.

JavaScript div ordering script bug (switches order of the two divs below)

Code:
http://jsfiddle.net/s4UQP/
^ Here is the best way to see the code and how it works with the divs
But here is the code anyway:
function move(from, to) {
document.getElementById('progress').innerHTML = '...';
from = parseInt(from,10);
to = parseInt(to,10);
tbc = document.getElementById(from);
before = document.getElementById(to);
containr = document.getElementById('alldivs');
neworder = 'Order: <select><option onclick="move(' + to + ',1)">1</option><option onclick="move(' + to + ',2)">2</option><option onclick="move(' + to + ',3)">3</option></select> <br>Send up | Send down<br>Bring to front (#1) | Send to back (#4)';
document.getElementById(from).getElementsByClassName('order')[0].innerHTML = neworder;
document.getElementById(from).getElementsByClassName('number')[0].innerHTML = to;
tempdiv = document.createElement('div');
tmphtml = document.getElementById(from).innerHTML;
tempdiv.className = 'holder';
tempdiv.innerHTML = tmphtml;
n = 0;
npieces = 4;
if (from < to) {
nochanges = to - from;
fromone = from + 1;
//alert(n+' '+to+' '+fromone);
for (n = fromone; n <= to; n++) {
//alert('down');
idnum = parseInt(document.getElementById(n).id,10);
//alert(idnum);
document.getElementById(n).getElementsByClassName('number')[0].innerHTML = (idnum - 1);
alert(document.getElementById(n).id);
document.getElementById(n).id = (idnum - 1);
//alert('down '+idnum+' to '+(idnum-1));
}
}
if (from > to) {
nochanges = from - to;
totone = to + 1;
for (n = to; n < from; n++) {
//alert('n is '+n+' going to '+to+' ends at '+totone);
//alert('up');
idnum = parseInt(document.getElementById(n).id,10);
//alert(idnum);
document.getElementById(n).getElementsByClassName('number')[0].innerHTML = (idnum + 1);
alert(document.getElementById(n).id);
document.getElementById(n).id = (idnum + 1);
//alert('up '+idnum+' to '+(idnum+1));
}
}
//tempdiv.id = 'span'+to;
if (from > to) {
containr.insertBefore(tempdiv, before);
}
if (from < to) {
before = to + 1;
containr.insertBefore(tempdiv, document.getElementById(before));
}
tbc.parentNode.removeChild(tbc);
tempdiv.id = to;
document.getElementById('progress').innerHTML = 'done';
}
The script works as you move a block (or div) up or down, but when you try to move a different block (e.g. the one at the top), it just switches around the first two blocks beneath it.
Could anyone give me any advice?
I don't know whether it's because of the order that the script was done in, or if it's something else. It's been confusing me for some time, and I'd really appreciate it if someone could look through it and give me some advice.
(I don't want to code it in jQuery, this is really just me trying to learn more JavaScript by coding something. If it's not the most efficient, secure, whatever, it's still just something with which I'm trying to teach myself JavaScript.)
Thank you for reading. (Please don't edit the JS Fiddle itself, but rather post any edits/improvements here. Thank you.)
[Edit: I'm not really writing a cliche sci-fi, they're just example divs because I couldn't think of anything better]
In the statement neworder =... you change the values of the onclick functions, but you only do this for the block that is about to be moved. The problem is that the other blocks also change positions. For instance, if you click on 'Send up' for block 2, then block 2 moves up to position 1 and block 1 moves down to position 2. But only the event handlers on block 2 are updated accordingly. So the next time you click on (what was originally) block 1, it will not behave correctly.
One solution would be to update the event handlers on all of the blocks that are affected every time one of them is moved. For instance, make a function called updateEventHandlers(blockNumber) and call it for all of the affected blocks.
However relying on IDs to indicate the position of a block and then fiddling with the IDs after they are moved can lead to all sorts of confusion. It is better either to keep an array or dictionary recording the positions of the blocks, or loop through them to determine their positions in the DOM each time you want to move them.
For instance the following code provides moveup, movedown and moveto functions using the latter method (it finds where the element is in the DOM and swaps it with the holder before or after). (JSFIDDLE)
function E(id) { return document.getElementById(id);}
var holders = document.getElementsByClassName('holder');
function moveup(id) {
for (var i = 0; i < holders.length - 1; i++) {
// Find the holder before the one we're interested in
if (holders[i + 1] == E(id)) {
// Swap their positions
E('alldivs').insertBefore(E(id), holders[i]);
break;
}
}
resetNumbers();
}
function movedown(id) {
for (var i = 1; i < holders.length; i++) {
// Find the holder after the one we're interested in
if (holders[i - 1] == E(id)) {
// Swap their positions
E('alldivs').insertBefore(holders[i], E(id));
break;
}
}
resetNumbers();
}
function moveto(id, position) {
if (position == holders.length) { // move to end
E('alldivs').appendChild(E(id));
}
else { // move before another holder
E('alldivs').insertBefore(E(id), holders[position - 1]);
}
resetNumbers();
}
function resetNumbers() {
// Reset all the numbers to reflect their current position
var numbers = document.getElementsByClassName('number');
for (var i = 0; i < numbers.length; i++) {
numbers[i].innerHTML = i + 1;
}
}​
A few other points:
clicking on the selects in your original code won't do anything initially, because no event handler is assigned to it until after one of the elements has been moved
there is a missing </div> from the end of the html
it is good practice to declare variables using var somewhere in your code
appendChild and insertBefore remove a node from its current position in the DOM before appending/inserting it in its new position, so there is no need to remove the element explicitly.
having moveup and movedown functions is better than only having moveto, which requires you to insert the current, preceding and following positions into the html and refresh them every time a block is moved.

Changing a class with z-index

I'm still in the process of learning JavaScript. and I would like to complete the task using only JavaScript and no Jquery.
I have multiple div/images that I’m trying to manipulate using the z-index, and a button that randomize the images to come to the front.
I got the random image array to work but as you could see in image[1]…setting each changeZ index will be laborious. So I’m embarking on changing the class’s (as seen in image[0] so I could add current to the new image and send current to the background on the next go around and then removing the class attribute. I have got the element to work separate but having trouble putting it together in a array.
function changeZIndex(i,id) {
document.getElementById(id).style.zIndex=i;};
function changeClassZIndex(i,tagName){
document.getElementsByTagName("*").style.zIndex=i;};
function getImage(){
var whichImage=Math.floor(Math.random()*3);
var image=new Array()
var currentPhoto = div.current
image[0]=function() {
changeZIndex(5,"scene1");
changeClassZIndex(-5,"current");
currentPhoto.removeClass('current')
document.getElementById("scene1").className += "current"; };
image[1]=function() {
changeZIndex(5,"scene2");
changeZIndex(-5,"scene1");
changeZIndex(-5,"scene3");
changeZIndex(-5,"scene");
};
image[2]=function() {
changeZIndex(5,"scene3");
changeZIndex(-5,"scene");
changeZIndex(-5,"scene2");
changeZIndex(-5,"scene1");
};
image[whichImage].apply(undefined);};
It's because document.getElementsByTagName() returns an array of elements, which you can't do operations like that on. Instead, you need to enumerate through them and do the operations individually.
Here's a working jsfiddle which shows exactly how to do it: jsfiddle
As a side note: if there's one thing a lot of web programming will teach you, its this:
Dont ever, ever, rule out jQuery as an option.
JQuery is your best friend, and the use of it in this situation would cut down your lines of code by well over half.
Firstly, I believe your problem is probably in changeClassZIndex(i,tagName)
which should probably look something like this:
if (document.getElementsByClassName == undefined) {
document.getElementsByClassName = function(className)
{
var hasClassName = new RegExp("(?:^|\\s)" + className + "(?:$|\\s)");
var allElements = document.getElementsByTagName("*");
var results = [];
var element;
for (var i = 0; (element = allElements[i]) != null; i++) {
var elementClass = element.className;
if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass))
results.push(element);
}
return results;
}
}
function changeClassZIndex(z,className) {
var e = document.getElementsByClassName(className);
for(var i = 0; i < e.length; i++) {
e[i].style.zIndex = z;
}
};
I am defining the getElementsByClassName function if it does not exist because some browsers may not support it.
I may suggest taking a different approach to your problem however:
var images = new Array("scene1", "scene2", "scene3");
var currentPhoto = div.current
var whichImage = Math.floor(Math.random()*images.length);
// change all images to the background
for(var i = 0; i < images.length; i++)
{
changeZIndex(-5, images[i]);
}
// change the one you want to the top
changeZIndex(5, images[whichImage]);
That way you do not have to write functions for each image, and adding images is as easy as adding to the array.

Categories

Resources