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;
?>
Related
I have a localStorage object like this:
Key: jpxun
Value: [{"id":"0","name":"royal"},{"id":"1","name":"tippins"},{"id":"4","name":"leviosa"},{"id":"5","name":"vicious"}]
I have this JS to display output the localStorage:
var jpxun = JSON.parse(localStorage.getItem('jpxun')) || [];
if (jpxun) {
var jpxun_length = jpxun.length;
} else {
var jpxun_length = 0;
}
var hst = document.getElementById("usernames");
var MyUsernames = JSON.parse(localStorage.getItem("jpxun"));
if (jpxun_length > 0) {
// declare array to hold items for outputting later in plain text format
var plain_text_array = [];
for (var i = 0; i < MyUsernames.length; i++) {
var un1 = MyUsernames[i].name;
hst.innerHTML += "<li>" +"<a id="+MyUsernames[i].id + " href='#content' onclick='deleteById(this)'>x </a>" + un1 + "</li>";
// add word to plain text array
plain_text_array.push(un1);
}
}
Each element is outputted in a list item with an 'x' as a hyperlink so that it can be clicked and that element is deleted from localStorage.
This is the code to delete the item from localStorage:
var deleteById = function ( self ){
MyUsernames = MyUsernames.filter(function(elem) {
return elem.id !== self.id;
});
localStorage.setItem("jpxun",JSON.stringify(MyUsernames));
self.parentNode.parentNode.removeChild(self.parentNode);
}
That works fine.
Unfortunately I don't really understand how the code works in deleteById.
As that is the case, I am stuck on working out how to delete the corresponding record from plain_text_array when its value is deleted from localStorage.
I would try to find the text in the array thats includes that string 'id="item_id"':
plain_text_array = plain_text_array.filter(item => !item.includes(`id="${self.id}"`));
Just add it in the end of deleteById function.
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 am working on a small JavaScript application that will users to click on buttons on the page and pass it through to thier basket. The problem I have with doing this is I am unsure as to handle multiple buttons within the same function. I do not want to have to write out different functions for each button.
I am trying to do it OOP and have this so far:
var shop = {};
shop.items = [];
shop.Item = function(item, description, price) {
this.item = item;
this.description = description;
this.price = price;
};
shop.print = function() {
var itemCon = document.getElementById('items'),
html = "";
for(var i = 0; i < this.items.length; i++) {
html += '<div id="item">';
for(prop in this.items[i]) {
html += '<p><span class="title">' + prop + '</span>: ' + this.items[i][prop] + '</p>';
};
html += '<button id="' + this.items[i].item + '">Add to Basket</button>'
html += '</div>';
};
itemCon.innerHTML += html;
};
shop.items[shop.items.length] = new shop.Item("Coat", "Warm", "20");
shop.items[shop.items.length] = new shop.Item("Coat", "Warm", "20");
shop.items[shop.items.length] = new shop.Item("Coat", "Warm", "20");
shop.items[shop.items.length] = new shop.Item("Coat", "Warm", "20");
var basket = {};
basket.items = [];
basket.Item = function(item, description, price) {
this.item = item;
this.description = description;
this.price = price;
};
basket.add = function(data) {
this.items[items.length] = new Item(data.item, data.description, data.price);
};
basket.costCalculate = function() {
var cost = 0,
html = "Total: " + cost;
for(var i = 0; i < this.items.length; i++) {
cost += items[i].price;
};
return html;
};
basket.print = function() {
var output;
for(var i = 0; i < this.items.length; i++) {
for(prop in this.items[i]) {
console.log(prop + ": " + this.items[i][prop]);
};
};
};
function init() {
shop.print()
};
window.onload = init;
How would I determine what item has been clicked in order to run basket.add(data). How would I also pass through the data to that function for each item.
Also how would one go about implementing closure? I understand that it is inner functions having access to the variables of the outer functions, is what I am doing working with closure so far?
Okay, you've made a pretty good start but here are a couple suggestions:
It's probably a good idea to only have one instance of each Item. By that I mean it looks like you create a bunch of Items for to populate your shop's inventory, so for example:
var coat = new Item("Coat", "Warm", 20);
shop.items.push(coat);
Now when you click on your UI element, you ideally want this same instance of coat to go into your basket as well, so:
// User clicks on UI element, which triggers the following to execute:
basket.add( someItemIdentifier );
So now if you ever decide to increase all your prices by $10, you can simply do:
shop.increasePricesBy = function(amount) {
for(var i = 0; i < shop.items.length; i++) {
shop.items[i].price += amount;
}
// execute some function to update existing baskets' totals
};
I hope this makes sense for why there should be one instance of each item that multiple collections refer to.
This begs the question how you can tie the customer's interaction to adding the correct item. One solution could be to use arbitrary IDs to track items. For example:
// Create new item with some randomly generated ID
var coat = new Item({
id: "93523452-34523452",
name: "Coat",
description: "Warm",
price: 20
});
shop.items = {}; // Use a hash so it's easier to find items
shop.items[coat.id] = coat;
And your UI element could be some div like so:
<div class="add-product-button" data-id="93523452-34523452">
Add your click handler:
// Pure JS solution - untested
var clickTargets = document.getElementsByClassName("add-product-button");
for(var i = 0; i < clickTargets.length; i++) {
var clickTarget = clickTargets[i];
clickTarget.onClick = function() {
var itemID = clickTarget.getAttribute("data-id");
var item = shop.items[itemID];
basket.add(item);
};
}
// Equivalent jQuery code
$(".add-product-button").click(function() {
var id = $(this).attr('data-id');
var item = shop.items[id];
basket.add(item);
});
While your basket implements add something like:
basket.add = function(items) {
this.items.push(item);
};
And your costCalculate method gets a whole lot easier:
basket.costCalculate = function() {
var cost = 0;
for(var i = 0; i < this.items.length; i++) {
cost += this.item[i].price;
}
return cost;
};
Instead of doing this:
shop.items[shop.items.length] = new shop.Item("Coat", "Warm", "20");
You can instead do:
shop.items.push(new shop.Item("Coat", "Warm", "20");
Probably a good idea to use a number instead of a string to represent the price.
In your shop.print loop, you probably don't want to hard code <div id="item"> because that will result in multiple divs with the same id.
Finally, I'm not going to try to answer your closure question here because I think that's been answered better than I can already so I'll just link you to some great resources that helped me understand it:
Best stackoverflow thread on how JS Closures work
MDN's doc on closures
Javascript: The Good Parts by Douglas Crockford. It's a tiny book, and talks about some great concepts - especially working with Prototypes which I suspect you'd find useful to help you with this project.
Let me know if you have any questions, I'm totally down to discuss them.
var ButtonFarmAtivada = new Array();
function X() {
var tableCol = dom.cn("td"); //cell 0
//create start checkbox button
ButtonFarmAtivada[index] = createInputButton("checkbox", index);
ButtonFarmAtivada[index].name = "buttonFarmAtivada_"+index;
ButtonFarmAtivada[index].checked = GM_getValue("farmAtivada_"+index, true);
FM_log(3,"checkboxFarm "+(index)+" = "+GM_getValue("farmAtivada_"+index));
ButtonFarmAtivada[index].addEventListener("click", function() {
rp_farmAtivada(index);
}, false);
tableCol.appendChild(ButtonFarmAtivada[i]);
tableRow.appendChild(tableCol); // add the cell
}
1) is it possible to create the button inside an array as I'm trying to do in that example? like an array of buttons?
2) I ask that because I will have to change this button later from another function, and I'm trying to do that like this (not working):
function rp_marcadesmarcaFarm(valor) {
var vListID = getAllVillageId().toString();
FM_log(4,"MarcaDesmarcaFarm + vListID="+vListID);
var attackList = vListID.split(",");
for (i = 0; i <= attackList.length; i++) {
FM_log(3, "Marca/desmarca = "+i+" "+buttonFarmAtivada[i].Checked);
ButtonFarmAtivada[i].Checked = valor;
};
};
For number 1) yes, you can.
function createInputButton(type, index) { // um, why the 'index' param?
// also, why is this function called 'createInputButton'
// if sometimes it returns a checkbox as opposed to a button?
var inputButton = document.createElement("input");
inputButton.type = type; // alternately you could use setAttribute like so:
// inputButton.setAttribute("type", type);
// it would be more XHTML-ish, ♪ if that's what you're into ♫
return inputButton;
}
I don't really understand part 2, sorry.