I have a huge array called newCombs when I call store.put(game) the tab turns white and is gone in chrome task manager. Basically the process just stops and it fails to store the array
var trans = this.db.transaction('Games', 'readwrite');
var store = trans.objectStore('Games');
store.get(new Date().toLocaleDateString() + ' ' + prize.value).onsuccess = function() {
var game = this.result;
game.combs = game.combs.concat(newCombs); //I'm appending to the game.combs array which is empty when I first run it (when it also crashes)
store.put(game);
}
trans.oncomplete = function(evt) {
arrLength = 0;
newCombs = [];
}
This is what game is equal to:
game = {
name: new Date().toLocaleDateString() + ' ' + prize.value,
date: new Date().toLocaleDateString(),
prize: prize.value,
playerData: [...],
points: {...}
}
The above part is a method of an object so this is not the window object everything works fine until the code hits the line with: store.put(game); the page just crashes.
As #paldepind suggests you are changing scope in the onsuccess event handler and losing sight of your custom object.
One way around this would be to take advantage of a closure and assign this to a local variable, before you define the anonymous callback function:
var trans = this.db.transaction('Games', 'readwrite');
var store = trans.objectStore('Games');
var that = this;
store.get(new Date().toLocaleDateString() + ' ' + prize.value).onsuccess = function() {
var game = that.result;
game.combs = game.combs.concat(newCombs);
store.put(game);
}
trans.oncomplete = function(evt) {
arrLength = 0;
newCombs = [];
}
Related
Supposed I have a function for previewing image
previewImages: function()
{
var preview = document.querySelector('#img_preview');
let iFileLength = this.files.length;
let oldValue = iFileLength;
console.log(oldValue);
}
this.oTweetImg.addEventListener("change", oHome.previewImages);
The 3 here is where I selected the 3 files. right after that I close and then pick again another file and it resets the length to 1. The 1 here should be 4
How can I save the previous/old length of an inputted file. I tried to put it on a variable, however it still resets the length.
Im using <input type="file" id="tweet_img" multiple/>
let oldValue = iFileLength; will be forgotten once the code exits previewImages. So the second time previewImages is called, there won't be another instance of oldValue. You will need to use closure (declare a variable outside the scope it's being used in, and manipulate that variable from that inner scope).
You can either store the latest length:
var lastSize = [];
var oHome = {
previewImages: function() {
var preview = document.querySelector('#img_preview');
lastSize = this.files.length;
console.log(lastSize);
}
};
this.oTweetImg.addEventListener("change", oHome.previewImages);
Or you can store all the past lengths:
var sizeHistory = [];
var oHome = {
previewImages: function() {
var preview = document.querySelector('#img_preview');
sizeHistory.push(this.files.length);
console.log(sizeHistory);
console.log(sizeHistory.reduce(function(sum, size){ return sum + size; }, 0));
}
};
this.oTweetImg.addEventListener("change", oHome.previewImages);
Try out the following way through which you will get the how many total images have selected
var totalImage = 0;
previewImages: function()
{
var preview = document.querySelector('#img_preview');
let iFileLength = this.files.length;
totalImage = totalImage + iFileLength;
console.log(totalImage); //4
}
this.oTweetImg.addEventListener("change", oHome.previewImages);
I want to access variables ie. distance, vertex2Position, path which in two seperate function, inside main function called getResult. How can I achieve this without altering my code or altering my code in minimum way.
function getResult() {
document.getElementById("vertex1").onchange = function() {
var vertex1 = document.getElementById("vertex1").value;
var vertex1Position = graph.node.findIndex(e => e.id == vertex1) + 1;
document.getElementById("output").textContent = vertex1Position;
var distance = execute(vertex1Position); // How can I access distance in my result variable
};
var vertex2Position = 0;
console.log("whats here");
document.getElementById("vertex2").onchange = function() {
var vertex2 = document.getElementById("vertex2").value;
vertex2Position = graph.node.findIndex(e => e.name == vertex2)+ 1; // I also want to access vertex2Position in my result variable which is in outer function
document.getElementById("secondOutput").textContent = vertex2Position;
var path = getPath(vertex2Position); //How can I access path in var result
};
var result = distance.vertex2Position; // I want to store distance and vertex2Position in result variable
document.getElementById("searchResult").innerHTML = "test" + result + "" + path + "."; // I also want to access path
}
You should use something like this :
var container = (function(){
var distance;
var vertex2P;
return {
setDistance: function(distance){
this.distance = distance;
},
getDistance: function(){return this.distance;},
setVertex2P: function(vertex2P){
this.vertex2P = vertex2P;
},
getVertex2P: function(){return this.vertex2P;},
}}());
And then you can get and set the values in other functions like this
var result = function(){
container.setDistance(2);
container.setVertex2P(3);
console.log(container.getDistance() + container.getVertex2P());
}
result(); // 5
These are(maybe ) the best practices you can use in Javascript with this you avoid the global variables and added privacy to your variables, hope it helps you.
P.S you can short this with ECMASCRIPT 6
In javascript, you need understand about scopes. In your code, the
main scope is the getResult() function, so if you want to access
variables inside sub functions (functions inside the getResult()
function), you'll need declare the variables at beginning of this main
scope.
Example:
function getResult() {
var distance,
path,
vertex1,
vertex2,
vertex1Position,
vertex2Position = 0;
document.getElementById("vertex1").onchange = function() {
vertex1 = document.getElementById("vertex1").value;
vertex1Position = graph.node.findIndex(e => e.id == vertex1) + 1;
document.getElementById("output").textContent = vertex1Position;
distance = execute(vertex1Position);
}
document.getElementById("vertex2").onchange = function() {
vertex2 = document.getElementById("vertex2").value;
vertex2Position = graph.node.findIndex(e => e.name == vertex2)+ 1;
document.getElementById("secondOutput").textContent = vertex2Position;
path = getPath(vertex2Position); //How can I access path in var result
};
result = distance.vertex2Position;
document.getElementById("searchResult").innerHTML = "test" + result + "" + path + ".";
}
Note: You're using functions triggered by "onchange" event, so your variables will initiate as undefined, except for "vertex2Position"
I am not very sure how to name the question. What i am trying to achieve is this..
I have a set of Global Variable, they will need to be replicated over and over, but assigned with different set's name example. For example
var start
var end
var time
And i have many set/model that i have to create and change, so i am wondering if it is possible to create 1 set and i just have a var modelnumber which then i can just copy and paste them and change the modelnumber so i wont have to change thousands of variable names?
Example
var modelnumber = "1";
var modelstart = modelnumber + "modelstart";
var modelend = modelnumber + "modelend";
var modeltime = modelnumber + "modeltime";
Edit: To provide more info
So i have model1.js , model2.js model3.js and so on....and all the variable names function names are the same, and to save me time, i want to write 1 set of code that i can just change the var modelname at the top of each field so i wont have to change the thousands of variable names and function names..
You can always write a function:
function createVariables(modelNumber) {
window[modelNumber + 'modelstart'] = 1;
window[modelNumber + 'modelend'] = 2;
window[modelNumber = 'modeltime'] = 3;
}
createVariables(1);
Or change it to however you want. :)
UPDATE: (use global in place of window for NodeJS).
I think you're looking for a normal object literal. You can specify the property keys of the object with strings, which will give you the dynamic effect you're looking for.
Here's an example, using a for loop to populate the object.
var models = {};
var number_of_keys = 1000;
for(var i = 1; i < number_of_keys; i++) {
var keyName = 'model' + i;
var model = {
'start': i + 'modelstart',
'end': i + 'modelend',
'time': i + 'modeltime'
}
models[keyName] = model;
}
console.log(models);
Update:
As an example of how you could access your populated models, consider the following:
// You can effectively replace the `1` in this example with any number:
var model1 = models['model1'];
// model1 would be:
// {
// 'start': '1modelstart',
// 'end' : '1modelend',
// 'time': '1modeltime'
// }
var start1 = model1.start;
var end1 = model1.end;
var time1 = model1.time;
// Pseudo-code
var modelN = models['modelN'];
var startN = modelN.start;
var endN = modelN.end;
var timeN = modelN.time;
HTH
You could (should?) use an object or an array of objects.
For example:
// The "Model"
var Model = function(start,end,time) {
this.start = start;
this.end = end;
this.time = time;
}
// One option.
// Assign "Model" to the models
var models = {
'm1': new Model(x,y,z),
'm2': new Model(a,b,c)
}
// Access values
if (models.m1) {
alert("m1 end:["+ models.m1.end +"]");
}
// Add a "new" model
models['ace'] = new Model(r,s,t);
// or even
models.club = new Model(e,f,g);
You could also extend it like so:
Model.prototype.debug = function(id) {
if (id) {
console.log("model id:["+ id +"]");
}
console.log("start:["+ this.start +"]");
console.log("end:["+ this.end +"]");
console.log("time:["+ this.time +"]");
}
Which you would call like so:
models.m1.debug();
Or even:
for(x in models) {
models[x].debug(x);
}
Here is a code snippet example.
var Model = function(start,end,time) {
this.start = start;
this.end = end;
this.time = time;
}
Model.prototype.debug = function(id) {
if (id) {
console.log("model id:["+ id +"]");
}
console.log("start:["+ this.start +"]");
console.log("end:["+ this.end +"]");
console.log("time:["+ this.time +"]");
}
var models = {
'm1' : new Model('x','y','z'),
'm2' : new Model('a','b','c')
};
models.ace = new Model('r','s','t');
for(x in models) {
models[x].debug(x);
}
In case this gets labeled as a duplicate or something similar; I just wanted to put it out there that I looked for an answer for about 3-4 days. The articles, topics and related questions that showed up did not solve my problem. If they do happen to be the solution, I currently don't and didn't understand why.
How can I, for example, loop through all instances of the player object and return each instance's value for the id property?
function player(id, damage, arena)
{
this.id = id;
this.damage = damage;
this.arena = arena;
}
var player1 = new player(101,10, true);
var player2 = new player(102,5, true);
var player3 = new player(103,20, true);
Don't laugh at me!
Even though I'm like 65% percent sure a string wouldn't serve as a reference
to an object, all my train of thoughts tend to revert back to something that works like this..
var txt = "";
for (i=1; i <= player_count; i++)
{
var x = "player"+i;
txt += " " + x.id;
}
document.GetElementById("someTextDivOrSomething").innerHTML = txt;
Can someone explain how I can go about doing this, or point me in the right direction?
You need some structure to hold the data, i.e. the representation of your players as you create them.
later on you can loop over the elements of your players collection
e.g.
let players = {};
...
players[101] = new player(101,10, true);
players[102] = new player(102,15, true);
players[103] = new player(103,20, true);
...
let txt = ""
for (let p of players) {
txt += " " + p.id
// note we need a name which is not "player" as that is taken
}
You can use a closure for the object constructor. The private variable players contains all instances of the class Player.
var Player = function () {
var players = [];
return function(id, damage, arena) {
this.id = id;
this.damage = damage;
this.arena = arena;
this.players = players;
this.players.push(this);
};
}();
var player1 = new Player(101, 10, true);
var player2 = new Player(102, 5, true);
var player3 = new Player(103, 20, true);
document.write(player1.players.length + '<br>'); // 3
document.write(player2.players.length + '<br>'); // 3
player3.players.forEach(function (a) { document.write('id: ' + a.id + '<br>'); }); // 101, 102, 103
I have a large array, with non-sequential IDs, that looks something like this:
PhotoList[89725] = new Array();
PhotoList[89725]['ImageID'] = '89725';
PhotoList[89725]['ImageSize'] = '123';
PhotoList[89726] = new Array();
PhotoList[89726]['ImageID'] = '89726';
PhotoList[89726]['ImageSize'] = '234';
PhotoList[89727] = new Array();
PhotoList[89727]['ImageID'] = '89727';
PhotoList[89727]['ImageSize'] = '345';
Etc....
I'm trying to figure out, given an ID, how can I can get the next and previous ID... So that I could do something like this:
<div id="current">Showing You ID: 89726 Size: 234</div>
Get Prev Get Next
Obviously, if we're at the end or beginning of the array we just a message...
Why don't you add properties 'Prev' & 'Next' to that array?
PhotoList[89725] = new Array();
PhotoList[89725]['Prev'] = 89724;
PhotoList[89725]['Next'] = 89726;
PhotoList[89725]['ImageID'] = '89725';
PhotoList[89725]['ImageSize'] = '123';
This is just 'doubly-linked list' data structure.
Based on your example the IDs are sequential...
This is another way of writing your example. new Array() really isn't what you should be using because those are objects you are creating. Also, I left the numbers as strings, but I'm not sure why you would want to do that. You could add next and prev like kuy suggested
PhotoList[89725] = {ImageID: '89725',
ImageSize: '123'};
PhotoList[89725] = {ImageID: '89726',
ImageSize: '234',
Next: '89727',
Prev: '89725'};
PhotoList[89725] = {ImageID: '89727',
ImageSize: '345'};
All of these are accessible just like your other structure.
There's really no way other than to iterate through the possible ids sequentially until you find one which has an entry in your array. For example:
function findClosest(arr, id, increasing) {
var step = increasing ? 1 : -1;
for(var i=id+step; i>=0 && i<=max_id; i+=step)
if( arr[id] )
return id;
}
Obviously, this approach requires that you keep track of the max_id so that you don't iterate forever; here I assume that it's a global variable, but you might want to make it a parameter to the findClosest function. You'd call this function like so:
var prev = findClosest(arr, id, false);
var next = findClosest(arr, id, true);
I agree with the rest quotes you should be using objects not an array. Also make sure you create new arrays using the literal notation and not the new keyword with built in types. The new keyword is bad news and you could clobber the global object. Check out JSLint.
var a = new Array(); //bad dont use
var a = []; //this is the best way to create a new array
var o = {}; //create new objects like this
As for the problem at hand. Why not write a simple container that has its own internal counter?
function PhotoListContainer(PhotoList)
{
if(PhotoList === undefined)
throw("no photo list");
this.counter = 0;
var self = this;
this.current = function(){
return PhotoList[self.counter];
};
this.next = function(){
return PhotoList[self.counter + 1];
};
this.prev = function(){
return PhotoList[self.counter - 1];
};
// You could even write a function that loops each value from the current counter :)
this.each_from_counter = function(callback){
for(var i = self.counter; i < PhotoList.length; i++)
{
callback(PhotoList[i], i);
self.counter++;
}
};
}
//use
var pc = new PhotoListContainer(PhotoList);
pc.counter = 500;
pc.next(); //returns the 501st object
pc.prev(); //returns the 499th object
pc.each_from_counter(function(photo, index){
photo.somehting;
});
No arrays at all are better..
images = {
0: {
size: 12345, /* dont realy need as you can use JS to mesure the size. */
title: "day 1 on holiday"
},
1: {
size: 13549, /* dont realy need as you can use JS to mesure the size. */
title: "day 2 on holiday"
},
2: {
size: 16548, /* dont realy need as you can use JS to mesure the size. */
title: "day 3 on holiday"
},
}
for(x in images){
/* x = "the id of the image." */
url[] = "/images/" + x + ".png";
title[] = images[x].title;
size[] = images[x].size;
console.log("File: " + url[x] + " , Title: " + title[x] + " , Size: " + size + "bytes")
}
var sibNum = 0;
var sibList = [];
var prevSiblingID = false;
for (n in w) {
sibNum++;
sibList[n] = {
title : n,
prevSiblingID : prevSiblingID
};
if (prevSiblingID) {
sibList[prevSiblingID].nextSiblingID = n;
}
prevSiblingID = n;
};
sibList[prevSiblingID].nextSiblingID = false;
you can use grep function and calculate prev or next item of specified array:
object = $.grep(data, function(e) {
if(e.id == yourId) {
return data[data.indexOf(e) + 1]; // or -1 for prev item
}
});
i think your image list will come from DB so you may can try this code, this code is working for me.
<?
$prev="";
$next="";
$cur=0;
$i=0;
$pid=$_GET['pid'];
while($rowcon=mysql_fetch_assoc($result))
{
$arr[$i]=$rowcon['pid'];
if($rowcon['pid']==$pid)
{
$cur=$i;
}
$i++;
}
if($cur<$num_rows)
$next=$arr[$cur+1];
else
$next="";
if($cur>0)
$prev=$arr[$cur-1];
else
$prev="";
echo $prev." ".$cur." ".$next;
?>