JavaScript Reference Several Images With Similar Names Without Linking to Each One - javascript

I have the following code which chooses a background image depending from the images array. The problem is that I have about 200 images and I was hoping there would be a quicker way to put all of them in the images array than have to list each image like I have the six currently. They have very similar names (i.e. image001, image002, ... image200) so if somehow the number could just be added onto the "image".
This would save me a lot of time and space. The code is below.
var images = [
'image0.png',
'image1.png',
'image2.png',
'image3.png',
'image4.png',
'image5.png'
];
$("#container").on("scroll", function(){
var $container = $("#container");
var $content = $("#content");
var totalScrollAmount = $content.height() - $container.height();
var percentScrolled = $container.scrollTop() / totalScrollAmount;
$content.css({
background:"url("+images[Math.floor(percentScrolled * images.length)]+")"
});
});

var images = [];
for(var i = 0; i < 200; i++)
images.push("image" + ("000" + i).substr(-3, 3) + ".png");

Here is a generator written as an IIFE
var images = (function (maxlen, arr, i) {
function pad3(i) { // helper
return ('000' + i).slice(-3);
}
arr || (arr = []); // defaults
i || (i = 0);
arr.length = maxlen;
for (; i < maxlen; ++i) { // do the loop
arr[i] = 'image' + pad3(i) + '.png';
}
return arr;
}(3)); // 3 for 3 items
images; // ["image000.png", "image001.png", "image002.png"]

Related

Google App Script Get Multiple Index Positions

I'm trying to figure out a way to get the index position of each repetition of a string.
The goal is to get each of those index positions and use the difference between each position to create a subtotal. The problem at hand is two fold. First, the distance between each string is not a standard length. Second, I seem to not be able to find out how to get multiple index positions of a particular string. I'm currently using the following code to cycle through different ranges to insert equations in to the sheet.
var Architecture = function(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
var data = activeSheet.getRange(18, 2, 7, activeSheet.getLastColumn()).getValues();
for (var i = 0; i < data.length; i++){
var rowData = data[i];
var checkData = data;
var row = checkData[i];
var colB = row[0];
if(colB == 'Subtotal'){
activeSheet.getRange(18 + i, 5, 1, data[0].length-4).setFormula('=iferror(sum(E' + (i+12) + ':E' + (i+17) + '))');
}else{
activeSheet.getRange(18 + i, 5).setFormula('=iferror(sum(F' + (i+18) + ':DU' + (i+18) + '))');
activeSheet.getRange(18 + i, 6)
.setFormula('=iferror(sum(filter(Invoices!$E:$E,Year(Invoices!$B:$B)=year(F$12),MONTH(Invoices!$B:$B)=Month(F$12),Invoices!$F:$F=$B' + (i+18) + ',Invoices!$A:$A=$C$2)))')
.copyTo(activeSheet.getRange('F18:DU23'));
}
}
};
var DueDiligence = function(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
var data = activeSheet.getRange(26, 2, 15, activeSheet.getLastColumn()).getValues();
for (var i = 0; i < data.length; i++){
var rowData = data[i];
var checkData = data;
var row = checkData[i];
var colB = row[0];
if(colB == 'Subtotal'){
activeSheet.getRange(26 + i, 5, 1, data[0].length-4).setFormula('=iferror(sum(E' + (i+12) + ':E' + (i+25) + '))');
}else{
activeSheet.getRange(26 + i, 5).setFormula('=iferror(sum(F' + (i+26) + ':DU' + (i+26) + '))');
activeSheet.getRange(26 + i, 6)
.setFormula('=iferror(sum(filter(Invoices!$E:$E,Year(Invoices!$B:$B)=year(F$12),MONTH(Invoices!$B:$B)=Month(F$12),Invoices!$F:$F=$B' + (i+26) + ',Invoices!$A:$A=$C$2)))')
.copyTo(activeSheet.getRange('F26:DU39'));
}
}
};
The goal would be to combine all these different functions into a single array that runs much quicker than the 18 seconds it currently takes to run.
EDIT
I've made some progress. Using the below function, I can get the index of each string, but it repeats that index position in the log for the number of rows that preceded it. For example, if the string is in index position two and then index position 10, the log shows 2,2,2,10,10,10,10,10,10,10,10 (only eight positions because 10-2=8).
var test = function(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
var data = activeSheet.getRange(14, 2, activeSheet.getLastRow()-13,1).getValues();
var newData = data.map(function(r){ return r[0]; });
//Logger.log(newData);
//Logger.log(data.indexOf("Subtotal", [i]));
for(var i = 0; i < data.length; i++){
Logger.log(newData.indexOf("Subtotal", [i]));
// }
}
};
You want to retrieve the indexes of all elements of an array called "Subtotal".
This can be done in a single line by combining map and filter:
var indexes = newData.map((element, i) => element === "Subtotal" ? i : "")
.filter(element => element !== "");
In this case, map returns an array with the matching indexes as well as empty strings (for unmatching indexes), and filter removes the empty string elements.
Edit:
If you want to retrieve an array with the differences between an index and the previous one, you can do this (the first index will be the same in this case):
var differences = indexes.map((element, i) => i == 0 ? element : element - indexes[i-1]);
Reference:
Array.prototype.map()
Array.prototype.filter()
Here's an example:
function getRowNumbersOfSameStrings() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getActiveSheet();
const rg=sh.getRange(2,1,sh.getLastRow()-1,1);
const vs=rg.getValues();
let u={};
vs.forEach(function(r,i){
if(!u.hasOwnProperty(r[0])) {
u[r[0]]=[];
u[r[0]].push(i+2);//row numbers
}else{
u[r[0]].push(i+2);//row numbers
}
});
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(JSON.stringify(u)), "Results");
}
Here's my sample data:
COL1,COL2,COL3,COL4,COL5,COL6,COL7,COL8
7,2,4,0,1,1,10,4
9,3,2,5,2,6,7,6
9,2,10,10,9,7,2,11
10,7,2,10,2,6,2,0
0,2,4,0,6,3,10,0
2,7,6,7,0,3,5,8
6,9,6,11,3,5,5,8
1,4,5,5,10,0,3,11
4,3,3,3,1,9,3,2
9,4,0,9,2,8,11,2
5,8,7,0,3,6,5,4
5,3,5,3,2,3,8,3
Results:
{"0":[6],"1":[9],"2":[7],"4":[10],"5":[12,13],"6":[8],"7":[2],"9":[3,4,11],"10":[5]}

Split javascript string into array

I have this javscript string:
response
"[[[#],[b,#],[b,w,b,b,b,#],[b,#],[b,w,w,b,#]],[[b,#],[b,b,#],[b,b,w,#],[b,b,b,#],[b,b,#]],[[b,#],[b,b,b,b,#],[b,w,#],[b,b,b,#],[b,#]],[[b,#],[b,#],[w,w,w,#],[b,b,w,w,#],[b,w,#]],[[b,#],[b,b,b,b,#],[b,w,b,#],[b,w,#],[b,b,#]]]"
This corresponds to a board game and which field (e.g [b,w,b,b,b,#]) is a cell with black and white pieces. The # is the top of the stack.
I need to parse this in order to create an array of tiles.
I have this:
XMLscene.prototype.readBoard = function(data){
var response = data.target.response;
console.log("REPONSE NO PARS" + response);
response = response.split("],");
console.log("REPONSE " + response);
response[0] = response[0].substring(1);
response[5] = response[5].substring(0, response[5].length - 2);
for(var i = 0; i < response.length; i++)
{
response[i] = response[i].substring(1);
response[i] = response[i].split("),");
for(var j = 0; j < response[i].length; j++)
response[i][j] = response[i][j].substring(5);
}
this.scene.board.loadTiles(response);
//this.scene.client.getPrologRequest('quit', 0, 1);
};
to be parsed in this function:
gameBoard.prototype.loadTiles = function(board){
console.log("BOARD : " + board);
this.tiles = [];
for (var i = 0; i < board.length; i++){
for (var j = 0; j < board[i].length; j++){
var player = board[i][j].split(",")[0];
console.log("PLAYER : " + player);
var type = board[i][j].split(",")[1];
console.log("Type : " + type);
if (type != "e") {
var tile = this.createTile(type, this.scene ,i*6 + j+100, player);
tile.line = i;
tile.col = j;
this.tiles.push(tile);
}
}
}
}
The board structure I want is something like this:
for the first stack: [#]
It's an empty cell
[b,#] - A cell with one piece - black
[b,w,w,b,#] - A cell with a black piece in the bottom, then two white pieces and a black on the top, therefore the black player is the owner of the stack!
The stack owner is the player that have his piece on the top of the stack (closest to #)
Is there any way to get an array with each stack being the element of it?
Regards
You could transform the data to JSON like this, ignoring the hashes as they seem to give information that is already known (the stack ends at the right):
var response = JSON.parse(response.replace(/,?#/g, '').replace(/[bw]/g, '"$&"'));
Then you can for instance identify the current player for a stack at (i, j), like this:
var player = board[i][j].slice(-1)[0]; // last element on the stack
Snippet:
// Sample data
var response = "[[[#],[b,#],[b,w,b,b,b,#],[b,#],[b,w,w,b,#]],[[b,#],[b,b,#],[b,b,w,#],[b,b,b,#],[b,b,#]],[[b,#],[b,b,b,b,#],[b,w,#],[b,b,b,#],[b,#]],[[b,#],[b,#],[w,w,w,#],[b,b,w,w,#],[b,w,#]],[[b,#],[b,b,b,b,#],[b,w,b,#],[b,w,#],[b,b,#]]]";
// Convert to nested array
var board = JSON.parse(response.replace(/,?#/g, '').replace(/[bw]/g, '"$&"'));
// Print the stack at 3, 3
console.log(board[3][3].join(','));
// Print player for that stack:
console.log(board[3][3].slice(-1)[0]);
A quick and dirty solution is to quote all your elements by using String.prototype.replace() and then put the entire result in an eval():
var str = "[[[#],[b,#],[b,w,b,b,b,#],[b,#],[b,w,w,b,#]],[[b,#],[b,b,#],[b,b,w,#],[b,b,b,#],[b,b,#]],[[b,#],[b,b,b,b,#],[b,w,#],[b,b,b,#],[b,#]],[[b,#],[b,#],[w,w,w,#],[b,b,w,w,#],[b,w,#]],[[b,#],[b,b,b,b,#],[b,w,b,#],[b,w,#],[b,b,#]]]";
var res = eval(str.replace(/[bw#]/g, "'$&'"));
console.log(res);
Modify your string to look like this...
var myString = '[[[#],[b,#],[b,w,b,b,b,#],[b,#],[b,w,w,b,#]],[[b,#],[b,b,#],[b,b,w,#],[b,b,b,#],[b,b,#]],[[b,#],[b,b,b,b,#],[b,w,#],[b,b,b,#],[b,#]],[[b,#],[b,#],[w,w,w,#],[b,b,w,w,#],[b,w,#]],[[b,#],[b,b,b,b,#],[b,w,b,#],[b,w,#],[b,b,#]]]'
replace elements with ""
Now run following:
var myArrayObject = JSON.parse(myString);
You just converted it to array.
Sample code:
https://fiddle.jshell.net/3gvzmwef/21/

Cannot read properties of an object

I have spent many hours on this irritating problem in my code. I define a class to hold several properties. I then populate those properties into a 2d array. From there, I then attempt to modify random elements in the 2d array. I keep getting the message
"Cannot read property of 'attribute' of undefined"
where attribute is any one of the three attributes in my object. Here is my code:
var table = new Array();
var adjacencyList = new Array();
var cell = function (prop) {
var atrbs = {
x: prop.x,
y: prop.y,
isVisited: prop.isVisited
}
return atrbs;
};
var createTable = function(size){
for(var row = 0; row < size; row++){
table[row] = new Array();
for(var column = 0; column < size; column++){
table[row][column] = new cell({x: row, y: column, isVisited: false});
}
}
};
function print(){
for(var row = 0; row < table.length; row++){
for(var column = 0; column < table[row].length; column++){
console.log(table[row][column]);
}
}
};
var randomizeMaze = function(){
var randomX = Math.floor((Math.random() * table.length));
var randomY = Math.floor((Math.random() * table.length));
var currentCell = table[randomX][randomY];
currentCell.isVisited = true;
adjacencyList.push(currentCell);
while( adjacencyList.length > 0 ) {
currentCell.isVisited = true;
var adjacentNodes = getAdjacentNodes(currentCell);
//randomly select a node to add to path
var nextInPath = adjacentNodes[Math.floor((Math.random() * adjacentNodes.length))];
//add to path to not visit it again
adjacencyList.push.apply(adjacencyList, adjacentNodes);
var removeNode = adjacencyList.indexOf(currentCell);
adjacencyList.splice(removeNode, 1);
//reset currentCell to random cell from resized list
currentCell = adjacencyList[Math.floor((Math.random() * adjacencyList.lenth))];
}
};
function getAdjacentNodes(pCell){
var adjacentNodes = new Array();
//check left
if(pCell.x - 1 >= 0){
var node = table[pCell.x-1][pCell.y];
adjacentNodes.push(node);
adjacencyList.push(node);
}
//check right
if(pCell.x + 1 < table.length){
var node = table[pCell.x+1][pCell.y];
adjacentNodes.push(node);
adjacencyList.push(node);
}
//check top
if(pCell.y - 1 >= 0){
var node = table[pCell.x][pCell.y - 1];
adjacentNodes.push(node);
adjacencyList.push(node);
}
//check bottom
if(pCell.y + 1 < table.length){
var node = table[pCell.x][pCell.y + 1];
adjacentNodes.push(node);
adjacencyList.push(node);
}
return adjacentNodes;
};
createTable(3);
//print();
randomizeMaze();
Whenever I try and access/change any property inside of a cell, namely in the functions 'randomeMaze' and 'getAdjacentNodes', it will throw the error I mentioned. I can print the objects to console, I see the objects as being populated when I debug. Maybe I'm missing something and am going crazy.
Any help would be greatly appreciated.

Multi-dimensional Javascript open array

I have difficulty with assigning and retrieving the values of elements in the open array, the array size and dimensions are not fixed so its due to expand or shrink during the iteration. I declare the array as var NODES[[]]; trying to assign, retrieving values and obtaining the length of any dimension in array results wrong values. Especially with the var le = NODES[0].length ; code I 'd expect to see the total length of first dimension.
var NODES =[[]]
scene = editor.scene;
scene.traverse( function(e) {
if ( (e instanceof THREE.Line) && (e.name = 'main line' ) )
{
for (i=0; i<e.geometry.vertices.length; i++){
var x = e.position.x+ e.geometry.vertices[i].x
var y = e.position.y+ e.geometry.vertices[i].y
var z = e.position.z+ e.geometry.vertices[i].z
NODES[node_cnt,0] = x;
NODES[node_cnt,1] = y;
NODES[node_cnt,2] = z;
node_cnt++;
}
cnt++;
};
var le = NODES[0].length ;
EXPECTED RESULT
NODES[0][0] = 10; NODES[0][1] = 20; NODES[0][3] = 30;
NODES[1][0] = 40; NODES[1][1] = 50; NODES[1][3] = 60;
NODES[2][0] = 70; NODES[2][1] = 80; NODES[2][3] = 90;
with `var le = NODES[0].length ;` I expect to see 3 because I'm requesting the length of 1st dimension
This is the javascript interpretation of multi dimensional array, NODES is an array which contains actually 3 array, every array contained in NODES contain a string:
var NODES = [[],[],[]];
for (var i = 0; i < 10 ; i++) {
NODES[0].push(i + 'x');
NODES[1].push(i + 'y');
NODES[2].push(i + 'z');
}
console.log(NODES[0].lenght);
If every contained array should contain one another array the sintax to do this should be:
NODES[0].push([i + 'x']);
Sorry, I'm not understand clearly what mean node_cnt and cnt, but I think you should do something like this:
var NODES =[[],[],[]]
scene = editor.scene;
scene.traverse( function(e) {
if ( (e instanceof THREE.Line) && (e.name = 'main line' ) )
{
for (i=0; i<e.geometry.vertices.length; i++){
var x = e.position.x+ e.geometry.vertices[i].x
var y = e.position.y+ e.geometry.vertices[i].y
var z = e.position.z+ e.geometry.vertices[i].z
NODES[0].push(x);
NODES[1].push(y);
NODES[2].push(z);
node_cnt++;
}
cnt++;
};
var le = NODES[0].length ;

Javascript grid calculation

I am creating a game where I represent boxes with a two dimensional array of their id.
var grid = [[X,X,X,X,X,X,X,X,X,X],
[X,X,4,4,4,4,X,X,X,X],
[X,3,3,3,3,X,X,X,X,X],
[X,X,X,2,2,2,2,X,X,X],
[X,1,1,1,1,5,5,5,5,5]];
The boxes stack on top of each other, and X represents a blank spot.
If one of the boxes are deleted I want any of the boxes above (That can fit) to shift down. So they are always neatly stacked.
So if I was to delete the box with ID: 1 I would get a new grid like this:
var grid = [[X,X,X,X,X,X,X,X,X,X],
[X,X,4,4,4,4,X,X,X,X],
[X,3,3,3,3,X,X,X,X,X],
[X,X,X,2,2,2,2,X,X,X],
[X,X,X,X,X,5,5,5,5,5]];
Then I would want Box: 3 to slide down into its spot like so:
var grid = [[X,X,X,X,X,X,X,X,X,X],
[X,X,4,4,4,4,X,X,X,X],
[X,X,X,X,X,X,X,X,X,X],
[X,X,X,2,2,2,2,X,X,X],
[X,3,3,3,3,5,5,5,5,5]];
Finally Box: 4 should move down into where 3 was:
var grid = [[X,X,X,X,X,X,X,X,X,X],
[X,X,X,X,X,X,X,X,X,X],
[X,X,4,4,4,4,X,X,X,X],
[X,X,X,2,2,2,2,X,X,X],
[X,3,3,3,3,5,5,5,5,5]];
Is there an easy way of doing this? I was thinking of a callback that checks the grid when a box is destroyed but what I came up with was mostly IF statements. Is there something elegant out there?
The box class itself also has the start position and its length:
box = {id: 3,
start: 1,
length: 4};
This is actually not an easy task. I created a little fiddle that does what you wanted to achieve (i think).
I extended the box prototype with some functions. My solution relies on the variables grid and blocks, but you could abstract that even more if you like to.
The functions testFunctionality and printGridToElement are just there for testing purposes.
My new Box prototype:
function Box(i, s, l) {
this.id = i;
this.start = s;
this.length = l;
this.row;
blocks.push(this);
}
Box.prototype.insertIntoGrid = function (row) {
this.row = row;
if (!grid[row]) grid[row] = [];
for (var i = 0; i < this.length; i++) {
grid[row][this.start + i] = this.id;
}
};
Box.prototype.destroy = function () {
blocks.splice(blocks.indexOf(this), 1);
this.removeFromGrid();
this.checkRemainingBlocksForMoveDown();
};
Box.prototype.checkRemainingBlocksForMoveDown = function () {
for (var i = 0; i < blocks.length; i++) {
var btmd = blocks[i].checkForMoveDown();
if (btmd) {
btmd[0].move(btmd[1]);
btmd[0].checkRemainingBlocksForMoveDown();
}
}
}
Box.prototype.move = function (row) {
this.removeFromGrid();
this.insertIntoGrid(row);
};
Box.prototype.removeFromGrid = function () {
for (var i = 0; i < this.length; i++) {
grid[this.row][this.start + i] = 0;
}
};
Box.prototype.checkForMoveDown = function () {
for (var i = 0; i < this.row; i++) {
var move = true;
for (var j = 0; j < this.length; j++) {
if (grid[i][this.start + j] != 0) {
move = false;
break;
}
}
if (move) {
return [this, i];
}
}
};
and the usage of it:
var b1 = new Box(1, 1, 4);
b1.insertIntoGrid(0);
var b2 = new Box(2, 3, 4);
b2.insertIntoGrid(1);
var b3 = new Box(3, 1, 4);
b3.insertIntoGrid(2);
var b4 = new Box(4, 2, 4);
b4.insertIntoGrid(3);
var b5 = new Box(5, 5, 5);
b5.insertIntoGrid(0);
b1.destroy();
b2.destroy();
b3.destroy();
NOTE: I designed the grid with 0 being the lowest row
I'm late, but here goes.
You should probably swap rows, and columns. That is make it like:
var rows = [];
column = [x,x,x,x,x,x,x,x];
rows.push(column);
Instead of:
var columns = [];
var row = [x,x,x,x,x,x,x,x];
columns.push(row);
This way a drop is just an array operation on columns. You can then do things like splice out a block, splice in a block, unshift, shift, and so on.
Do the array operations before animations, but not before you get the column, and row information from the grid.
You can even name the methods that do it by array methods. shift drops the bottom block, splice(start, stop, [optional]new block). Like that.
#Markai did swap the columns, and rows in their answer, but I thought I'd add some clarity.
This is what I came up with (Not working but the gist)
fallCheck = function(deletedPosition, deletedLength) {
var fallable = grid.reduce(
function(array, row) {
var unique = row.filter(function(item, i, ar) { return ar.indexOf(item) === i;});
var id = unique.find( function(boxId) {
var box = boxes.iterate("id", boxId, Phaser.Group.RETURN_CHILD); //Finds the instance within a Phaser Group
return (box.start >= deletedPosition) && (box.start + box.length) <= (deletedPosition + deletedLength);
});
if (id != -1) array.push(id);
}, []);
if (fallable.length > 0) { fall(fallable[0]); } //fall simply moves the box to the lowest position on the grid
};

Categories