I call the function
animate(0,"mainNav",0.02,0.04);
And the declaration
function animate(num, element, transitionUnit, delayUnit) {
var delay = 0;
transition = 0;
//var delayUnit = 0.02; transitionUnit = 0.04;
var x = document.getElementById(element).getElementsByTagName("LI");
for (i = 0; i <= x.length - 1; i++) {
x[i].style.WebkitTransform = "translate3d(" + num + "px,0,0)";
x[i].style.transition = transition + "s " + delay + "s ease-in-out";
delay += delayUnit;
transition += transitionUnit;
if (x[i].querySelectorAll('ul li').length > 0) {
x[i].style.background = "rgba(0,0,0,0.35)";
}
}
}
If I uncomment...
//var delayUnit = 0.02; transitionUnit = 0.04;
...It works flawlessly.
But I want to use it with other functions that send different delayUnits and transitionUnits. Am I missing something?
Explicitly declare all the variables:
function animate(num, element, transitionUnit, delayUnit) {
var delay = 0;
var transition = 0;
var x = document.getElementById(element).getElementsByTagName("LI");
for (var i = 0; i <= x.length - 1; i++) {
x[i].style.WebkitTransform = "translate3d(" + num + "px,0,0)";
x[i].style.transition = transition + "s " + delay + "s ease-in-out";
delay += delayUnit;
transition += transitionUnit;
if (x[i].querySelectorAll('ul li').length > 0) {
x[i].style.background = "rgba(0,0,0,0.35)";
}
}
}
Using implicit globals in for loops causes problems.
As aSeptik mentioned, you might be inverting values:
animate(0,"mainNav",0.04,0.02);
Related
I am building a very simple memory game for a small project. The logic is as follows:
click on the input field to choose with how many pairs would you like to play
create divs with classes card1, card2 etc.
clone divs and randomize their place in the array
Here is my script (fork in JSFiddle):
$(".button").click(function () {
// get the value from the input
var numCards = parseInt($('input').val());
for (var i = 1; i <= numCards; i++) {
// create the cards
$(".container").append("<div class='card" + i + " cards'></div>") &&
$(".card" + i).clone().appendTo(".container");
}
// randomize cards in stack
var cards = $(".cards");
for (var i = 0; i < cards.length; i++) {
var target = Math.floor(Math.random() * cards.length - 1) + 1;
var target2 = Math.floor(Math.random() * cards.length - 1) + 1;
var target3 = Math.floor(Math.random() * cards.length - 1) + 1;
cards.eq(target).before(cards.eq(target2)).before(cards.eq(target3));
}
});
what I need now is to adjust the 3rd step, meaning to dynamically create the target vars, and the last line of the code
cards.eq(target).before(cards.eq(target2)).before(cards.eq(target3));
So please make me a suggestion - how would you do it? And bare in mind this is a project for beginners. Thank you!
$(".button").click(function () {
// get the value from the input
var numCards = parseInt($('input').val());
for (var i = 1; i <= numCards; i++) {
// create the cards
$(".container").append("<div class='card" + i + " cards'></div>") &&
$(".card" + i).clone().appendTo(".container");
}
var parent = $(".container");
var divs = parent.children();
while (divs.length) {
parent.append(divs.splice(Math.floor(Math.random() * divs.length), 1)[0]);
}
});
see jsfidle: http://jsfiddle.net/007y4rju/8/
source: http://jsfiddle.net/C6LPY/2/
Here is the version of the code in jsfiddle - http://jsfiddle.net/007y4rju/6/
Please, check if the behavior is consistent with the original code.
$(document).ready(function () {
$(".button").click(function () {
// get the value from the input
var numCards = parseInt($('input').val());
for (var i = 1; i <= numCards; i++) {
// create the cards
$(".container").append("<div class='card" + i + " cards'></div>") &&
$(".card" + i).clone().appendTo(".container");
}
// randomize cards in stack
var cards = $(".cards");
var startTarget = Math.floor(Math.random() * cards.length - 1) + 1;
var collection = cards.eq(startTarget);
var nextTarget;
var i;
for (i = 0; i < cards.length; i++) {
nextTarget = Math.floor(Math.random() * cards.length - 1) + 1;
collection.before(cards.eq(nextTarget));
}
});
});
You can randomize index in a class name (card%i%) when cloning divs. Then you don't need to shuffle cloned divs; you can append them as is.
$(".button").click(function () {
// get the value from the input
var numCards = parseInt($('input').val());
for (var i = 1; i <= numCards; i++) {
// create the cards
$(".container").append("<div class='card" + i + " cards'></div>");
}
var aIndices = [];
for (var i = 1; i <= numCards; i++) {
var ix;
do ix = Math.round(Math.random() * (numCards - 1)) + 1;
while (aIndices.indexOf(ix) >= 0);
aIndices.push(ix);
// clone
$(".card" + ix).clone().appendTo(".container");
}
});
I have been trying to write code that would use an embedded for loop to calculate the number of sections inside of each article (there is more than one so I can't use getID) in a document. When the button is clicked the code works but the numbers it calculates are completely off which means something isn't counting correctly. Here is my function:
<script>
function Calculations() {
var a = document.getElementsByTagName("article");
var s = 0;
var z = 0;
var x;
for (x = 0; x < a.length; x++) {
var cn = a[x].childNodes;
z++
for (i = 0; i < cn.length; i++) {
if (cn[i].nodeType == 1) {
if (cn[i].tagName == "P"); {
s++;
}
}
}
alert("Article " + z + " has " + s + " section.")
s = 0
}
alert("There are " + a.length + " total articles.")
}
</script>
Thank you so much for your help!
I am new to JavaScript. I would like to add to add two buttons for my visitors to control font size. I would like to include two tags - 'p' and 'blockquote". Can you please help me edit this code in order to include both?
var min = 8;
var max = 18;
function increaseFontSize() {
var p = document.getElementsByTagName('p');
for (i = 0; i < p.length; i++) {
if (p[i].style.fontSize) {
var s = parseInt(p[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != max) {
s += 1;
}
p[i].style.fontSize = s + "px"
}
}
function decreaseFontSize() {
var p = document.getElementsByTagName('p');
for (i = 0; i < p.length; i++) {
if (p[i].style.fontSize) {
var s = parseInt(p[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != min) {
s -= 1;
}
p[i].style.fontSize = s + "px"
}
}
Thank you.
Here's a working version:
http://jsfiddle.net/ny4p7pg9/
I took the liberty of refactoring a bit the functions to make the code more parameterized.
function changeFontSize(delta) {
var tags = document.querySelectorAll('p,blockquote');
for (i = 0; i < tags.length; i++) {
if (tags[i].style.fontSize) {
var s = parseInt(tags[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != max) {
s += delta;
}
tags[i].style.fontSize = s + "px"
}
}
function increaseFontSize() {
changeFontSize(1);
}
function decreaseFontSize() {
changeFontSize(-1);
}
Instead of using:
p = document.getElementsByTagName('p');
you could, instead use:
elems = document.querySelectorAll('p, blockquote');
(the variable name is irrelevant, and was changed only because the elements are no longer exclusively <p> elements):
function increaseFontSize() {
var elems = document.querySelectorAll('p, blockquote');
for (i = 0; i < elems.length; i++) {
if (elems[i].style.fontSize) {
var s = parseInt(elems[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != max) {
s += 1;
}
elems[i].style.fontSize = s + "px"
}
}
var min = 8;
var max = 18;
function increaseFontSize() {
var elems = document.querySelectorAll('p, blockquote');
for (i = 0; i < elems.length; i++) {
if (elems[i].style.fontSize) {
var s = parseInt(elems[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != max) {
s += 1;
}
elems[i].style.fontSize = s + "px"
}
}
function decreaseFontSize() {
var elems = document.querySelectorAll('p, blockquote');
for (i = 0; i < elems.length; i++) {
if (elems[i].style.fontSize) {
var s = parseInt(elems[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != min) {
s -= 1;
}
elems[i].style.fontSize = s + "px"
}
}
document.querySelector('#increase').addEventListener('click', increaseFontSize);
document.querySelector('#decrease').addEventListener('click', decreaseFontSize);
<button id="increase">↑A</button>
<button id="decrease">A↓</button>
<p>Some text to have its text adjusted by the buttons just up there.</p>
<blockquote>Some text in a blockquote</blockquote>
The querySelectorAll() method accepts CSS-style selectors, and returns a (non-live) NodeList, and is supported in all modern browsers, including IE from version 8 onwards.
That said, it's probably better to increase the font-size of the <body> element, otherwise font-adjustment is redundant (since other elements will still be unclear), so, instead, I'd suggest:
function increaseFontSize() {
// retrieving, and caching, the <body> element:
var body = document.body,
// finding the current computed fontSize of the <body> element, parsing it
// as a float (though parseInt() would be just as safe, really):
currentFontSize = parseFloat(window.getComputedStyle(body, null).fontSize);
// if the currentFontSize is less than the specified max:
if (currentFontSize < max) {
// we set the fontSize of the <body> to the incremented fontSize,
// increasing the current value by 1, and concatenating with the 'px' unit:
body.style.fontSize = ++currentFontSize + 'px';
}
}
function decreaseFontSize() {
var body = document.body,
currentFontSize = parseFloat(window.getComputedStyle(body, null).fontSize);
if (currentFontSize > min) {
body.style.fontSize = --currentFontSize + 'px';
}
}
var min = 8;
var max = 18;
function increaseFontSize() {
var body = document.body,
currentFontSize = parseFloat(window.getComputedStyle(body, null).fontSize);
if (currentFontSize < max) {
body.style.fontSize = ++currentFontSize + 'px';
}
}
function decreaseFontSize() {
var body = document.body,
currentFontSize = parseFloat(window.getComputedStyle(body, null).fontSize);
if (currentFontSize > min) {
body.style.fontSize = --currentFontSize + 'px';
}
}
document.querySelector('#increase').addEventListener('click', increaseFontSize);
document.querySelector('#decrease').addEventListener('click', decreaseFontSize);
<button id="increase">↑A</button>
<button id="decrease">A↓</button>
<p>Some text to have its text adjusted by the buttons just up there.</p>
<blockquote>Some text in a blockquote</blockquote>
References:
document.body.
document.querySelectorAll().
Window.getComputedStyle().
I am trying to render child elements of an element if the element is in view or removing the content if not in view like below on scroll event like below
list.addEventListener('scroll', function () {
var elements = document.querySelectorAll('.aBox');
var toBe = counter - 1 - elements.length;
for (var i = 0; i < elements.length; i++) {
var inView = visibleY(elements[i]),
ele = elements[i].querySelector('.item');
if (inView === false && ele) {
console.log("Not in visible, keeping it none");
var height = elements[i].clientHeight;
elements[i].style.height = height + "px";
elements[i].innerHTML = "";
} else if(!ele){
console.log('Placing the content');
var minArray = arr[toBe + 1 + i],
str = "";
for (var j = 0; j < minArray.length; j++) {
str += "<div class='item'>" + minArray[j] + "</div>";
}
elements[i].innerHTML = str;
}
}
});
It seems working but if I have a look at the DOM this is not working as expected. Someone please help me to find the problem, fiddle.
Update
function updateData(callback) {
var elements = document.querySelectorAll('.aBox');
elements = Array.prototype.slice.call(elements);
var toBe = counter - 1 - elements.length;
async.each(elements, function (element, cb) {
var inView = $(element).is_on_screen(),
ele = element.querySelector('.item');
if (inView == false && ele) {
console.log("Not in visible, keeping it none");
var height = element.clientHeight;
element.style.height = height + "px";
element.innerHTML = "";
} else if (!ele && inView) {
console.log('Placing the content');
var minArray = arr[toBe + 1 + i],
str = "";
if (typeof minArray === "object") {
for (var j = 0; j < minArray.length; j++) {
str += "<div class='item'>" + minArray[j] + "</div>";
}
element.innerHTML = str;
}
}
cb();
}, function () {
callback()
});
}
Fiddle
Hi I have solved this problem. Posting here, so that it will be more helpful for people who want to work on mobiles to display very large lists with virtual scrolling
var arr = new Array(10000);
for (var i = 0; i < arr.length; i++) {
arr[i] = "Hello Dudes..." + i;
}
Array.prototype.chunk = function (chunkSize) {
var array = this;
return [].concat.apply([],
array.map(function (elem, i) {
return i % chunkSize ? [] : [array.slice(i, i + chunkSize)];
}));
}
arr = arr.chunk(50);
var list = document.getElementById('longList');
var button = document.getElementById('loadMore');
var counter = arr.length,
aBoxLen = 1;
function appendBox() {
var div = document.createElement('div'),
str = "";
div.className = "aBox";
var minArray = arr[counter - aBoxLen];
for (var i = 0; i < minArray.length; i++) {
str += "<div class='item'>" + minArray[i] + "</div>";
}
div.innerHTML = str;
div.setAttribute('index', counter - aBoxLen);
var box = document.querySelector('.aBox');
if (box) {
list.insertBefore(div, box);
} else {
list.appendChild(div);
}
aBoxLen += 1;
}
appendBox();
button.addEventListener('click', function () {
appendBox();
});
$.fn.is_on_screen = function () {
var win = $(window);
var viewport = {
top: win.scrollTop(),
left: win.scrollLeft()
};
viewport.right = viewport.left + win.width();
viewport.bottom = viewport.top + win.height();
var bounds = this.offset();
bounds.right = bounds.left + this.outerWidth();
bounds.bottom = bounds.top + this.outerHeight();
return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
};
function updateData(callback) {
var elements = document.querySelectorAll('.aBox');
elements = Array.prototype.slice.call(elements);
var toBe = counter - 1 - elements.length;
async.each(elements, function (element, cb) {
var inView = $(element).is_on_screen(),
ele = element.querySelector('.item');
if (inView == false && ele) {
console.log("Not in visible, keeping it none");
var height = element.clientHeight;
element.style.height = height + "px";
element.innerHTML = "";
} else if (!ele && inView) {
console.log('Placing the content');
console.log(element.getAttribute('index'));
var minArray = arr[element.getAttribute('index')],
str = "";
for (var j = 0; j < minArray.length; j++) {
str += "<div class='item'>" + minArray[j] + "</div>";
}
element.innerHTML = str;
}
cb();
}, function () {
// callback()
});
}
var delay = false;
var timeout = null;
list.addEventListener('touchmove', function () {
clearTimeout(timeout);
timeout = setTimeout(function () {
updateData();
}
}, delay);
});
None of the solutions were specifically designed for mobiles, so I have implemented this.
I think there is lots of space for improvement in this. If anybody want to improve it, please feel free to make it
Demo
I'm having a hard time finding a way to insert falling letters into my code. My task is to have a text string and have all the even-placed letters fall from the top and the odd-placed letters fly from the bottom and come together to form the string in the center.
So for instance, I have: <span class="uName">John Doe</span>
I would like the letters: O, N, D, E to fall from the top.
Likewise: J H _ O to fly up from the bottom. (keeping their respective horizontal positions).
Here's what I have so far, however I'm fairly inexperienced with JavaScript/JQuery and I can't get it to run.
vertical = new Array(80);
var textPos = 0;
for(var i = 0; i < 80; ++i) {
vertical[i] = textPos;
textPos += 5;
}
function poz(){
document.getElementsByClassName("tops").style.top = '0px';
document.getElementsByClassName("bottoms").style.bottom = '0px';
animate();
}
function animate(){
for(var j = 0; j < 80; ++j) {
document.getElementsByClassName("tops").style.top = vertical[j] + "px";
document.getElementsByClassName("bottoms").style.bottom = vertical[j] + "px";
}
}
$('.uName').each(function(){
var letters = $(this).text().split('');
$(this).text('');
for(var i = 0; i < letters.length; i++){
if(i % 2 == 0){
$(this).append('<span class="tops">' + letters[i] + '</span>');
}
else{
$(this).append('<span class="bottoms">' + letters[i] + '</span>');
}
}
poz();
});
Thanks so much in advanced!
P.S. If this task can be achieved with just CSS3, I would much prefer that option but I'm not sure if it's possible.
//css
.bottoms{
margin-top:200px!important;
}
//Script
vertical = new Array(80);
var textPos = 0;
for(var i = 0; i < 80; ++i) {
vertical[i] = textPos;
textPos += 5;
}
function poz(){
// $(".tops").css('top','0px');
// $(".bottoms").css('bottom','0px');
//document.getElementsByClasjqsName("bottoms").style.bottom = '0px';
animate();
}
function animate(){
for(var j = 0; j < 80; ++j) {
//alert(vertical[j]);
//$(".tops").css('top',vertical[j]+'px');
//$(".bottoms").css('bottom',vertical[j]+'0');
if(vertical[j]<101){
$(".tops").animate({top:vertical[j]+'px'},500);
$(".bottoms").animate({bottom:vertical[j]+'px'},500);
$(".tops").css('position','relative');
$(".bottoms").css('position','relative');
$(".tops").css('float','left');
$(".bottoms").css('float','left');
}
// document.getElementsByClassName("tops").style.top = vertical[j] + "px";
// document.getElementsByClassName("bottoms").style.bottom = vertical[j] + "px";
}
}
$('.uName').each(function(){
var letters = $(this).text().split('');
$(this).text('');
for(var i = 0; i < letters.length; i++){
if(i % 2 == 0){
$(this).append('<span class="tops">' + letters[i] + '</span>');
}
else{
$(this).append('<span class="bottoms">' + letters[i] + '</span>');
}
}
poz();
});
//NEW Fiddle link http://jsfiddle.net/PP44C/7/
Now everything is fine as you want . check it