I am having a problem defining a class method:
this.method = function(){...}
I get an error thrown at the "." after "this".
If I declare the method directly using method(){...}, I am unable to reference it in other methods as it shows that the method is undefined.
The method I want to deifne is shuffleBoard(). How do I do it?
class Board {
constructor(size,boardId){
this.boardId = boardId;
switch(size){
case "medium":
var boardSize = 560;
var tiles = 7*7;
break;
case "large":
boardSize = 720;
tiles = 9*9;
break;
default:
boardSize = 320;
tiles = 4*4;
break;
}
var container = $(this.boardId+" .tiles-container");
var row = 0;
var loopArray = [];
for(var i = 0;i < tiles; i++){
var tile = document.createElement("div");
loopArray.push(i);
var text = i+1;
tile.setAttribute("index",i+1);
tile.id = i+1;
if(i == tiles - 1){
var empty = "empty"
}
tile.setAttribute("class","tile "+empty);
tile.innerText = text;
container.append(tile);
(function(){
tile.onclick = function(){
var tileObject = new Tile(this.getAttribute("index"));
console.log(tileObject.move());
}
})()
var prevRow = row;
if(i%4 == 0 && i != 0){
row++
}
if(row > prevRow){
var positionX = 0;
}
else{
var positionX = (i%4)*80;
}
var positionY = row*80;
tile.style.top=positionY+"px";
tile.style.left=positionX+"px";
console.log(i+"---"+row+"////"+prevRow);
}
setTimeout(function(){this.shuffleBoard(loopArray);},4000);
return container;
}
this.shuffleBoard = function(arr){
var i = 0;
console.log(this.boardId);
$(this.boardId+" .tiles-container tile").forEach(function(el){
var shuffled = shuffle(arr);
el.innerText = shuffled[i];
arr.pop(arr[i]);
i++
});
}
}
It seems like you are using ES6 syntax. In ES6 write functions like
shuffleBoard() {
// rest of the code
}
and to access it use this keyword. like this.shuffleBoard().
To call it in setTimeout, use arrow functions
setTimeout(() => { this.shuffleBoard(loopArray); }, 4000);
1.You have to use an arrow function to keep the scope, because otherwise this would be pointing to the new function created in the timeout.
setTimeout(() => {
this.shuffleBoard(loopArray);
}, 4000);
2.The constructor mustn't return anything because it prevents it from returning the object it constructs
3.jQuery uses .each() to iterate over jQuery objects instead of .forEach().
I put the notes directly in the code as comments as well:
class Board {
constructor(size, boardId) {
this.boardId = boardId;
switch (size) {
case "medium":
var boardSize = 560;
var tiles = 7 * 7;
break;
case "large":
boardSize = 720;
tiles = 9 * 9;
break;
default:
boardSize = 320;
tiles = 4 * 4;
break;
}
var container = $(this.boardId + " .tiles-container");
var row = 0;
var loopArray = [];
for (var i = 0; i < tiles; i++) {
var tile = document.createElement("div");
loopArray.push(i);
var text = i + 1;
tile.setAttribute("index", i + 1);
tile.id = i + 1;
if (i == tiles - 1) {
var empty = "empty"
}
tile.setAttribute("class", "tile " + empty);
tile.innerText = text;
container.append(tile);
(function() {
tile.onclick = function() {
var tileObject = new Tile(this.getAttribute("index"));
console.log(tileObject.move());
}
})()
var prevRow = row;
if (i % 4 == 0 && i != 0) {
row++
}
if (row > prevRow) {
var positionX = 0;
} else {
var positionX = (i % 4) * 80;
}
var positionY = row * 80;
tile.style.top = positionY + "px";
tile.style.left = positionX + "px";
console.log(i + "---" + row + "////" + prevRow);
}
setTimeout(() => { //use arrow function to keep the scope
this.shuffleBoard(loopArray);
}, 4000);
//return container; returning the container here prevents the constructor from returning the constructed object
}
shuffleBoard(arr) {
var i = 0;
console.log(this.boardId);
$(this.boardId + " .tiles-container tile").each(function(el) { //jQuery uses .each instead of forEach
var shuffled = shuffle(arr);
el.innerText = shuffled[i];
arr.pop(arr[i]);
i++
});
}
}
let board = new Board("medium", "myboard");
console.log(board.shuffleBoard);
board.shuffleBoard([]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
shuffleBoard = function(arr){
// rest of code
})
Then you can use method as:
let board = new Board()
board.shuffleBoard()
way1:move this.propertyName to constructor
class Board{
constructor(size,boardId){
this.boardId = boardId;
switch(size){
case "medium":
var boardSize = 560;
var tiles = 7*7;
break;
case "large":
boardSize = 720;
tiles = 9*9;
break;
default:
boardSize = 320;
tiles = 4*4;
break;
}
var container = $(this.boardId+" .tiles-container");
var row = 0;
var loopArray = [];
for(var i = 0;i < tiles; i++){
var tile = document.createElement("div");
loopArray.push(i);
var text = i+1;
tile.setAttribute("index",i+1);
tile.id = i+1;
if(i == tiles - 1){
var empty = "empty"
}
tile.setAttribute("class","tile "+empty);
tile.innerText = text;
container.append(tile);
(function(){
tile.onclick = function(){
var tileObject = new Tile(this.getAttribute("index"));
console.log(tileObject.move());
}
})()
var prevRow = row;
if(i%4 == 0 && i != 0){
row++
}
if(row > prevRow){
var positionX = 0;
}
else{
var positionX = (i%4)*80;
}
var positionY = row*80;
tile.style.top=positionY+"px";
tile.style.left=positionX+"px";
console.log(i+"---"+row+"////"+prevRow);
}
setTimeout(function(){this.shuffleBoard(loopArray);},4000);
this.shuffleBoard = function(arr) {
var i = 0;
console.log(this.boardId);
$(this.boardId + " .tiles-container tile").forEach(function(
el
) {
var shuffled = shuffle(arr);
el.innerText = shuffled[i];
arr.pop(arr[i]);
i++;
});
}
return container;
}
}
way2:change this.propertyName to a method in className.prototype
class Board {
constructor(size, boardId) {
this.boardId = boardId;
switch (size) {
case "medium":
var boardSize = 560;
var tiles = 7 * 7;
break;
case "large":
boardSize = 720;
tiles = 9 * 9;
break;
default:
boardSize = 320;
tiles = 4 * 4;
break;
}
var container = $(this.boardId + " .tiles-container");
var row = 0;
var loopArray = [];
for (var i = 0; i < tiles; i++) {
var tile = document.createElement("div");
loopArray.push(i);
var text = i + 1;
tile.setAttribute("index", i + 1);
tile.id = i + 1;
if (i == tiles - 1) {
var empty = "empty";
}
tile.setAttribute("class", "tile " + empty);
tile.innerText = text;
container.append(tile);
(function() {
tile.onclick = function() {
var tileObject = new Tile(this.getAttribute("index"));
console.log(tileObject.move());
};
})();
var prevRow = row;
if (i % 4 == 0 && i != 0) {
row++;
}
if (row > prevRow) {
var positionX = 0;
} else {
var positionX = (i % 4) * 80;
}
var positionY = row * 80;
tile.style.top = positionY + "px";
tile.style.left = positionX + "px";
console.log(i + "---" + row + "////" + prevRow);
}
setTimeout(function() {
this.shuffleBoard(loopArray);
}, 4000);
return container;
}
shuffleBoard(arr) {
var i = 0;
console.log(this.boardId);
$(this.boardId + " .tiles-container tile").forEach(function(el) {
var shuffled = shuffle(arr);
el.innerText = shuffled[i];
arr.pop(arr[i]);
i++;
});
}
}
Related
I've got a small web app in development to simulate the Ising model of magnetism. I've found that the animation slows down considerably after a few seconds of running, and it also doesn't loop after 5 seconds like I want it to with the command:
setInteval(main, 500)
I've added start and stop buttons. When I stop the animation, and then restart it, it begins fresh at the usual speed, but again slows down.
My question is: what steps can I take to troubleshoot and optimize the performance of my canvas animation? I hope to reduce or mitigate this slowing effect.
JS code:
window.onload = function() {
var canvas = document.getElementById("theCanvas");
var context = canvas.getContext("2d");
var clength = 100;
var temperature = 2.1;
var playAnim = true;
canvas.width = clength;
canvas.height = clength;
var imageData = context.createImageData(clength, clength);
document.getElementById("stop").addEventListener("click",function(){playAnim=false;});
document.getElementById("start").addEventListener("click",function(){playAnim=true;});
function init2DArray(xlen, ylen, factoryFn) {
//generates a 2D array of xlen X ylen, filling each element with values defined by factoryFn, if called.
var ret = []
for (var x = 0; x < xlen; x++) {
ret[x] = []
for (var y = 0; y < ylen; y++) {
ret[x][y] = factoryFn(x, y)
}
}
return ret;
}
function createImage(array, ilen, jlen) {
for (var i = 0; i < ilen; i++) {
for (var j = 0; j < jlen; j++) {
var pixelIndex = (j * ilen + i) * 4;
if (array[i][j] == 1) {
imageData.data[pixelIndex] = 0; //r
imageData.data[pixelIndex+1] = 0; //g
imageData.data[pixelIndex+2] = 0; //b
imageData.data[pixelIndex+3] = 255; //alpha (255 is fully visible)
//black
} else if (array[i][j] == -1) {
imageData.data[pixelIndex] = 255; //r
imageData.data[pixelIndex+1] = 255; //g
imageData.data[pixelIndex+2] = 255; //b
imageData.data[pixelIndex+3] = 255; //alpha (255 is fully visible)
//white
}
}
}
}
function dU(i, j, array, length) {
var m = length-1;
//periodic boundary conditions
if (i == 0) { //top row
var top = array[m][j];
} else {
var top = array[i-1][j];
}
if (i == m) { //bottom row
var bottom = array[0][j];
} else {
var bottom = array[i+1][j];
}
if (j == 0) { //first in row (left)
var left = array[i][m];
} else {
var left = array[i][j-1];
}
if (j == m) { //last in row (right)
var right = array[i][0];
} else {
var right = array[i][j+1]
}
return 2.0*array[i][j]*(top+bottom+left+right); //local magnetization
}
function randInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
var myArray = init2DArray(clength, clength, function() {var c=[-1,1]; return c[Math.floor(Math.random()*2)]}); //creates a 2D square array populated with -1 and 1
function main(frame) {
if (!playAnim){return;} // stops
window.requestAnimationFrame(main);
createImage(myArray, clength, clength);
context.clearRect(0,0,clength,clength);
context.beginPath();
context.putImageData(imageData,0,0);
for (var z = 0; z < 10*Math.pow(clength,2); z++) {
i = randInt(clength-1);
j = randInt(clength-1);
var deltaU = dU(i, j, myArray, clength);
if (deltaU <= 0) {
myArray[i][j] = -myArray[i][j];
} else {
if (Math.random() < Math.exp(-deltaU/temperature)) {
myArray[i][j] = -myArray[i][j];
}
}
}
}
var timer = setInterval(main, 500);
}
I made a puzzle game in javascript. I have made objects to keep some attributes relevant to the each pazzle squares. I want to get the object id which is relevant to the onclick.(not the div id). How to get the specific object id relevant to the clicked div?
window.onload = function() {
createDivs();
objects();
random();
onclickeventHanlder(event);
};
var getId;
var x = 3;
var counting = 0;
var tileSize = 600 / x;
var array2 = [];
var object = [];
function createDivs() {
var count = 0;
for (var i = 0; i < x; i++) {
for (var j = 0; j < x; j++) {
var id = i + "" + j;
var element = document.createElement('div');
element.setAttribute("class", "pieces");
element.setAttribute("id", id);
element.style.width = 600 / x + "px";
element.style.height = 600 / x + "px";
element.style.margin = "0px auto";
element.style.overflow = "hidden";
element.setAttribute("onclick", "onclickeventHanlder(this)");
if (count > 0) { // to break row-wise
if (i == count && j == 0) {
element.style.clear = "both";
}
}
element.style.float = "left";
document.getElementById('puzzle-body').appendChild(element);
}
count++;
}
}
function objects(){
var count = 0;
for (var i = 0; i < x; i++) {
for (var j = 0; j < x; j++) {
var objName = new Object();
objName.position = -(j * tileSize) + "px" + " " + -(i * tileSize) + "px";
objName.divID = document.getElementById(i + "" + j);
objName.id = count;
if(count<x*x-1){
objName.state = true; // if image is there
}else{
objName.state = false; // if image isn't there
}
object[count] = objName;
count++;
}
}
}
function reset(){
var looping = 0;
for (var i = 0; i < x; i++) {
for (var j = 0; j < x; j++) {
var obj = object[looping];
if(obj.id<8){
var urlString = 'url("../images/Golden.jpg")';
obj.divID.style.backgroundImage = urlString;
obj.divID.style.backgroundPosition = obj.position;
}
looping++;
}
}
}
function random(){
var array = [];
while (array.length < ((x * x) - 1)) {
var randomnumber = Math.floor(Math.random() * ((x * x) - 1));
var found = false;
for (var i = 0; i < array.length; i++) {
if (array[i] == randomnumber) {
found = true;
break;
}
}
if (!found) {
array[array.length] = randomnumber;
}
}
var looping = 0;
for (var i = 0; i < x; i++) {
for (var j = 0; j < x; j++) {
if (looping < x * x-1) {
var random = array[looping];
var obj = object[random];
var obj2 = object[looping];
if(obj.id<8){
var urlString = 'url("../images/Golden.jpg")';
obj.divID.style.backgroundImage = urlString;
obj.divID.style.backgroundPosition = obj2.position;
}
}
looping++;
}
}
}
function onclickeventHanlder(event) {
var pos = event;
}
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().
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Html
<html>
<head>
<script type="text/javascript" src="/test.js"></script>
<script type="text/javascript">
start();
</script>
</head>
<body>
</body>
</html>
Java script
var points = 1;
var points1;
var DELAY = 30;
var SPEED = 5;
var MAX_DY = 12;
var OBSTACLE_WIDTH = 30;
var OBSTACLE_HEIGHT = 100;
var TERRAIN_WIDTH = 10;
var MIN_TERRAIN_HEIGHT = 20;
var MAX_TERRAIN_HEIGHT = 50;
var POINTS_PER_ROUND = 5;
var DUST_RADIUS = 3;
var DUST_BUFFER = 10;
var NUM_OBSTACLES = 3;
var copter;
var dy = 0;
var clicking = false;
var score; // text you see on the screen
var obstacles = [];
var top_terrain = [];
var bottom_terrain = [];
var dust = [];
function start(){
starta();
}
function starta() {
setup();
setTimer(game, DELAY);
mouseDownMethod(onMouseDown);
mouseUpMethod(onMouseUp);
setTimer(points2, 10)
}
function points2(){
points1 = points/100
return points1;
}
function setup() {
setBackgroundColor(Color.black);
copter = new WebImage("image.png");
copter.setSize(25, 50);
copter.setPosition(getWidth()/3, getHeight()/2);
copter.setColor(Color.blue);
add(copter);
addObstacles();
addTerrain();
score = new Text("0");
score.setColor(Color.white);
score.setPosition(10, 30);
add(score);
}
function updateScore() {
points += POINTS_PER_ROUND;
score.setText(points);
}
function game() {
updateScore();
if (hitWall()) {
lose();
return;
}
var collider = getCollider();
if (collider != null) {
if (collider != copter) {
lose();
return;
}
}
if (clicking) {
dy -= 1;
if (dy < -MAX_DY) {
dy = -MAX_DY;
}
} else {
dy += 1;
if (dy > MAX_DY) {
dy = MAX_DY;
}
}
copter.move(0, dy);
moveObstacles();
moveTerrain();
moveDust();
addDust();
}
function onMouseDown(e) {
clicking = true;
}
function onMouseUp(e) {
clicking = false;
}
function addObstacles() {
for (var i = 0; i < NUM_OBSTACLES; i++) {
var obstacle = new WebImage("image.jpg");
obstacle.setSize(50, 100);
obstacle.setColor(Color.green);
obstacle.setPosition(getWidth() + i * (getWidth()/NUM_OBSTACLES),
Randomizer.nextInt(0, getHeight() - OBSTACLE_HEIGHT));
obstacles.push(obstacle);
add(obstacle);
}
}
function moveObstacles() {
for (var i=0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
obstacle.move(-points1, 0);
if(obstacle.getX() < 0) {
obstacle.setPosition(getWidth(),
Randomizer.nextInt(0, getHeight() - OBSTACLE_HEIGHT));
}
}
}
function hitWall() {
var hit_top = copter.getY() < 0;
var hit_bottom = copter.getY() + copter.getHeight() > getHeight();
return hit_top || hit_bottom;
}
function lose() {
stopTimer(game);
var text = new Text("You Lose!");
text.setColor(Color.red);
text.setPosition(getWidth()/2 - text.getWidth()/2,
getHeight()/2);
add(text);
}
function getCollider() {
var topLeft = getElementAt(copter.getX()-1, copter.getY()-1);
if (topLeft != null) {
return topLeft;
}
var topRight = getElementAt(copter.getX() + copter.getWidth() + 1,
copter.getY() - 1);
if (topRight != null) {
return topRight;
}
var bottomLeft = getElementAt(copter.getX()-1,
copter.getY() + copter.getHeight() + 1);
if (bottomLeft != null) {
return bottomLeft;
}
var bottomRight = getElementAt(copter.getX() + copter.getWidth() + 1,
copter.getY() + copter.getHeight() + 1);
if (bottomRight != null) {
return bottomRight;
}
return null;
}
function addTerrain() {
for (var i=0; i <= getWidth() / TERRAIN_WIDTH; i++) {
var height = Randomizer.nextInt(MIN_TERRAIN_HEIGHT, MAX_TERRAIN_HEIGHT);
var terrain = new Rectangle(TERRAIN_WIDTH, height);
terrain.setPosition(TERRAIN_WIDTH * i, 0);
terrain.setColor(Color.green);
top_terrain.push(terrain);
add(terrain);
height = Randomizer.nextInt(MIN_TERRAIN_HEIGHT, MAX_TERRAIN_HEIGHT);
var bottomTerrain = new Rectangle(TERRAIN_WIDTH, height);
bottomTerrain.setPosition(TERRAIN_WIDTH * i,
getHeight() - bottomTerrain.getHeight());
bottomTerrain.setColor(Color.green);
bottom_terrain.push(bottomTerrain);
add(bottomTerrain);
}
}
function moveTerrain() {
for (var i=0; i < top_terrain.length; i++) {
var obj = top_terrain[i];
obj.move(-points1, 0);
if (obj.getX() < -obj.getWidth()) {
obj.setPosition(getWidth(), 0);
}
}
for (var i=0; i < bottom_terrain.length; i++) {
var obj = bottom_terrain[i];
obj.move(-points1, 0);
if (obj.getX() < -obj.getWidth()) {
obj.setPosition(getWidth(), getHeight() - obj.getHeight());
}
}
}
function addDust() {
var d = new Circle(DUST_RADIUS);
d.setColor("#ffd700");
d.setPosition(copter.getX() - d.getWidth(),
copter.getY() + DUST_BUFFER);
dust.push(d);
add(d);
}
function moveDust() {
for (var i=0; i < dust.length; i++) {
var d = dust[i];
d.move(-points1, 0);
d.setRadius(d.getRadius() - 0.1);
if(d.getX() < 0) {
remove(d);
dust.remove(i);
i--;
}
}
}
Okay so here is my script. The script works perfectly fine on a codehs sandbox, but now that I want to set it on my own website it is not working. Could some one please help me out. Thank you.
Could some one please tell me how I would execute this code from test.js. Thank you.
You need to include the .js to your HTML page, like this:
<script type="text/javascript" src="/test.js"></script>
<script type="text/javascript">
start(); //starts your program
</script>
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