Losing object reference on lookup in Javascript - javascript

I'm working on an extension for Google Chrome and I ran into the following situation:
I'm trying to get all the existing tabs from all the opened windows in the same instance of Google Chrome. I manage to get them and construct an array of objects that contain the relevant data for me.
When I look at the constructed array using console.log (which is saved for future use also) I can see the collection of objects, but I can't reference them (when I try I get undefined).
I tried to save the array outside my object in a container, but nothing changes.
Any idea why the reference to the objects go away when I try to look them up? Thanks.
Here is the code:
(function(window){
//defining a namespace
var example = {
bmarksmaster: (function() {
var bmarksmaster = function() {
return new bmarksmaster.fn.init();
}
bmarksmaster.fn = bmarksmaster.prototype = {
debug: false,
tabs: [],
constructor: bmarksmaster,
init: function() {
return this;
},
windowParser: function(ctx, filter) {
var local = ctx;
var filter = filter;
return function(wObj) {
if((wObj !== null) && (wObj !== undefined)) {
for(var idx in wObj) {
var cw = wObj[idx];
if((cw.tabs !== null) && (cw.tabs !== undefined)) {
var cwtabs = cw.tabs;
for(var tabIdx in cwtabs) {
local.tabs.push(filter(tabIdx, cwtabs[tabIdx]));
}
}
}
}
};
},
getTabs: function() {
var returnData = [];
chrome.windows.getAll(
{
"populate": true
}, this.windowParser(this, function(i, e) {
var data = {};
if(!e.incognito) {
data["title"] = e.title;
data['url'] = e.url;
data['favicon'] = e.favIconUrl || "";
}
return data;
}));
return this.tabs;
},
getTab: function(callback) {
this.getTabs();
for (var tabIdx in this.tabs) {
if(callback(tabIdx, this.tabs[tabIdx])) {
return this.tabs[tabIdx];
}
}
},
getTabsData: function(callback) {
var data = [];
var tabs = [];
tabs = this.getTabs();
console.log(this.tabs[0]);
for (var tabIdx in tabs) {
console.log(tabs[tabIdx]);
var tabData = callback(tabIdx, tabs[tabIdx]);
if(tabData) {
data.push(tabData);
}
}
return data;
},
setDebug: function() {
this.debug = true;
},
resetDebug: function() {
this.debug = false;
}
};
bmarksmaster.fn.init.prototype = bmarksmaster.fn;
return bmarksmaster;
})()
};
window.example = example;
})(window);
//end of bmarksmaster.js file
console.log(example.bmarksmaster().getTabs()); //this works, I can see the array
console.log(example.bmarksmaster().getTabs()[0]); //this doesn't work, I get undefined, never mind the shortcut

I think the logic in your code is wrong. It is a bit convoluted and hard to follow. I would recommend rewriting it a bit to be simpler. Something like this might help get you started. It collects all the windows, putts all the tabs into the tabs var.
var tabs = [];
chrome.windows.getAll({ populate: true}, function(windows) {
var localTabs = windows.reduce(function(a, b){
return a.tabs.concat(b.tabs);
});
tabs = localTabs.filter(function(element){
return !element.incognito;
});
})

Related

JavaScript array has elements but length is zero

I've done some searching around the web and nothing seems to solve my problem. I have the following jQuery code:
function youtube_data_parser(data) {
//---> parse video data - start
var qsToJson = function(qs) {
var res = {};
var pars = qs.split('&');
var kv, k, v;
for (i in pars) {
kv = pars[i].split('=');
k = kv[0];
v = kv[1];
res[k] = decodeURIComponent(v);
}
return res;
}
//---> parse video data - end
var get_video_info = qsToJson(data);
if (get_video_info.status == 'fail') {
return {
status: "error",
code: "invalid_url",
msg: "check your url or video id"
};
} else {
// remapping urls into an array of objects
//--->parse > url_encoded_fmt_stream_map > start
//will get the video urls
var tmp = get_video_info["url_encoded_fmt_stream_map"];
if (tmp) {
tmp = tmp.split(',');
for (i in tmp) {
tmp[i] = qsToJson(tmp[i]);
}
get_video_info["url_encoded_fmt_stream_map"] = tmp;
}
//--->parse > url_encoded_fmt_stream_map > end
//--->parse > player_response > start
var tmp1 = get_video_info["player_response"];
if (tmp1) {
get_video_info["player_response"] = JSON.parse(tmp1);
}
//--->parse > player_response > end
//--->parse > keywords > start
var keywords = get_video_info["keywords"];
if (keywords) {
key_words = keywords.replace(/\+/g, ' ').split(',');
for (i in key_words) {
keywords[i] = qsToJson(key_words[i]);
}
get_video_info["keywords"] = {
all: keywords.replace(/\+/g, ' '),
arr: key_words
};
}
//--->parse > keywords > end
//return data
return {
status: 'success',
raw_data: qsToJson(data),
video_info: get_video_info
};
}
}
function getVideoInfo() {
var get_video_url = $('#ytdlUrl').val();
var get_video_id = getUrlVars(get_video_url)['v'];
var video_arr_final = [];
var ajax_url = "video_info.php?id=" + get_video_id;
$.get(ajax_url, function(d1) {
var data = youtube_data_parser(d1);
var video_data = data.video_info;
var player_info = data.video_info.player_response;
var video_title = player_info.videoDetails.title.replace(/\+/g, ' ');
var fmt_list = video_data.fmt_list.split(',');
var video_thumbnail_url = video_data.thumbnail_url;
var video_arr = video_data.url_encoded_fmt_stream_map;
//create video file array
$.each(video_arr, function(i1, v1) {
var valueToPush = {};
valueToPush.video_url = v1.url;
valueToPush.video_thumbnail_url = video_thumbnail_url;
valueToPush.video_title = video_title;
$.each(fmt_list, function(i2, v2) {
var fmt = v2.split('/');
var fmt_id = fmt[0];
var fmt_quality = fmt[1];
if (fmt_id == v1.itag) {
valueToPush.fmt_id = fmt_id;
valueToPush.fmt_quality = fmt_quality;
}
});
video_arr_final.push(valueToPush);
});
});
return video_arr_final;
}
function getUrlVars(url) {
var vars = {};
var parts = url.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m, key, value) {
vars[key] = value;
});
return vars;
}
function fillInOptions(ytOptions) {
//console.log(ytOptions);
//alert(ytOptions[0]);
var ytFill = ytOptions;
console.log(ytFill);
//ytFill.forEach(function(i,v) {
var ytdlOptions = $('#ytdlOptions');
ytFill.forEach(function(i,v) {
console.log(i);
ytdlOptions.append(new Option(v.fmt_quality, v.fmt_id));
});
return true;
}
function showYTDLLoader() {
$('#ytdlInput').fadeOut(1000, function() {
$('#ytdlLoader').fadeIn(500);
});
var options = getVideoInfo();
//console.log(options);
if (fillInOptions(options) == true) {
//do rest
}
}
function showYTDLOptions() {
return true;
}
function startDownload() {
showYTDLLoader();
}
function hideYTDLLoader() {
$('#ytdlLoader').fadeOut(500);
}
function animateCSS(element, animationName, callback) {
const node = $(element);
node.addClass(animationName);
function handleAnimationEnd() {
node.removeClass(animationName);
node.animationend = null;
if (typeof callback === 'function') callback();
}
node.animationend = handleAnimationEnd();
}
When my button is clicked, I call showYTDLLoader() which gets an array of objects from the YouTube API that looks like this:
[
{
"video_url": "https://r7---sn-uxanug5-cox6.googlevideo.com/videoplayback?expire=1572496003&ei=Iw66Xa24H8PL3LUPiN25mAs&ip=2001%3A8003%3A749b%3Aa01%3A5cd8%3Ac610%3A6402%3Ad0fe&id=o-ADsVnoOoBQ6-SWzYZU7gHES06s7xQptJG6hn9WcakITY&itag=22&source=youtube&requiressl=yes&mm=31%2C29&mn=sn-uxanug5-cox6%2Csn-ntqe6n7r&ms=au%2Crdu&mv=m&mvi=6&pl=39&initcwndbps=1655000&mime=video%2Fmp4&ratebypass=yes&dur=917.768&lmt=1572418007364260&mt=1572474311&fvip=4&fexp=23842630&c=WEB&txp=5535432&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cmime%2Cratebypass%2Cdur%2Clmt&sig=ALgxI2wwRgIhAIp-4gyUTLoXFetbY0ha_YnR7DJqsp_MNjjIxqDdfPZJAiEA_WPd21jgX9broBcigf8rcSEVoJb2_NX7t3XZQqytsSM%3D&lsparams=mm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHylml4wRAIgacvP3zjEq-rVEZFrX7a_hC6TR-Zab7Ii-Fbaupjs_PcCIHdZht4l4ioYL3ERz7WNiSbnOnhm5iYxEECaQXPP2hUp",
"video_title": "Arnold Schwarzenegger on Son-in-law Chris Pratt, Pranking Sylvester Stallone & Terminator’s Return",
"fmt_id": "22",
"fmt_quality": "1280x720"
},
{
"video_url": "https://r7---sn-uxanug5-cox6.googlevideo.com/videoplayback?expire=1572496003&ei=Iw66Xa24H8PL3LUPiN25mAs&ip=2001%3A8003%3A749b%3Aa01%3A5cd8%3Ac610%3A6402%3Ad0fe&id=o-ADsVnoOoBQ6-SWzYZU7gHES06s7xQptJG6hn9WcakITY&itag=18&source=youtube&requiressl=yes&mm=31%2C29&mn=sn-uxanug5-cox6%2Csn-ntqe6n7r&ms=au%2Crdu&mv=m&mvi=6&pl=39&initcwndbps=1655000&mime=video%2Fmp4&gir=yes&clen=44248820&ratebypass=yes&dur=917.768&lmt=1572416976690256&mt=1572474311&fvip=4&fexp=23842630&c=WEB&txp=5531432&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cmime%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&sig=ALgxI2wwRQIhANTZJlBHFWQWCnfK11yvLiPUV26c6NzvqIMKjDwmsByMAiBUSy0ZJMo4GdHSiRU4xBDDLxLtzwKZAqAKCiB-1aViDQ%3D%3D&lsparams=mm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHylml4wRAIgacvP3zjEq-rVEZFrX7a_hC6TR-Zab7Ii-Fbaupjs_PcCIHdZht4l4ioYL3ERz7WNiSbnOnhm5iYxEECaQXPP2hUp",
"video_title": "Arnold Schwarzenegger on Son-in-law Chris Pratt, Pranking Sylvester Stallone & Terminator’s Return",
"fmt_id": "18",
"fmt_quality": "640x360"
}
]
But when I try and loop through each entry with fillInOptions(), my loop is never completed because the length is apparently zero. However, when I dump the array using console.log() it tells me the length is 2, and displays the above. I need to be able to add each option to my dropdown.
Thankyou!
UPDATE: Added full code, sorry!
It looks like your .forEach() is the root of the problem. The parameters of a forEach are currentValue, index like this: array.forEach(function(currentValue, index) {}); but it looks like you're using them in the opposite way
Try rewriting that iteration to this:
ytFill.forEach(function(v, i) {
console.log(i);
ytdlOptions.append(new Option(v.fmt_quality, v.fmt_id));
});
Notice the difference in the order of v and i in the parameters.

JS: dynamically populate/combine object with nested objects/properties > do we have a simpler way?

The problem: I've a JS global var that I've to check if it as an object with "menus configurations" and populate with the missing configurations.
So this work is based on this AS2:
var result_array = re.result.items;
_global.menu_array = new Array();
var menu_type_num:Number = -1;
var menu_group_num:Number = -1;
var menu_id_num:Number = -1;
for (var i=0; i<result_array.length; i++){
if (menu_type_num != result_array[i].menu_type){
menu_type_num = result_array[i].menu_type;
menu_group_num = -1;
var type_array:Array = new Array();
_global.menu_array[menu_type_num] = type_array;
}
if (menu_group_num != result_array[i].menu_group){
menu_group_num = result_array[i].menu_group;
var group_array:Array = new Array();
_global.menu_array[menu_type_num][menu_group_num] = group_array;
}
var menu_obj:Object = new Object();
menu_id_num = menu_obj.menu_id = Number(result_array[i].menu_id);
menu_obj.menu_text = result_array[i].menu_text;
_global.menu_array[menu_type_num][menu_group_num][menu_id_num] = menu_obj;
}
I've reached to this solution in JS:
result.then(function(res)
{
if(!_MEV2_GLOBAL.hasOwnProperty("menu_array"))
{
_MEV2_GLOBAL.menu_array = {};
}
res.forEach(r =>
{
if(!_MEV2_GLOBAL.menu_array.hasOwnProperty(r.menu_type))
{
_MEV2_GLOBAL.menu_array[r.menu_type] = {};
}
if(!_MEV2_GLOBAL.menu_array[r.menu_type].hasOwnProperty(r.menu_group))
{
_MEV2_GLOBAL.menu_array[r.menu_type][r.menu_group] = {};
}
if(!_MEV2_GLOBAL.menu_array[r.menu_type][r.menu_group].hasOwnProperty(r.menu_id))
{
_MEV2_GLOBAL.menu_array[r.menu_type][r.menu_group][r.menu_id] = {
menu_id: r.menu_id,
menu_text: r.menu_text
};
}
}
}
This works but doing an if for every sublevel... Do I have another way, something with reduce or whatever, more effective and concise?
I know a little about JS but I'm afraid my solution isn't the best aproach. Or am I falling to the "root of all evil" :P
EDIT:
The input comes from an IndexedDB "table", so the result is made of objects ("lines") similar to the one on the picture:
for example, "t_menus_gre" select is the input
This resultSet must be inserted on a GlobalVar, that should follow this structure:
this object is my GlobalVar and should include a subObject['menu_array'] with menus configs by type/group/id
Okay... I honestly don't think I understood the logic behind that menu configuration, but based solely on your code I could make the following improvements:
result.then(res => {
_MEV2_GLOBAL.menu_array = _MEV2_GLOBAL.menu_array || {};
const array = _MEV2_GLOBAL.menu_array;
res.forEach(r => {
array[r.menu_type] = array[r.menu_type] || {};
array[r.menu_type][r.menu_group] = array[r.menu_type][r.menu_group] || {};
array[r.menu_type][r.menu_group][r.menu_id] = array[r.menu_type][r.menu_group][r.menu_id] || { menu_id: r.menu_id, menu_text: r.menu_text };
});
});
If you just want to verify if a value is defined, javascript always evaluates null, undefined, false, "" and 0 as false.
That way, when you execute array[r.menu_type] = array[r.menu_type] || {};, if array[r.menu_type] is undefined, it receives {}.
Hope that helps you in some way.

Adding html item to infoWindow - ArcGIS Javascript API 3.18

This question regarding a web app built using the ArcGIS Javascript API 3.18. I am trying to add an dojo select to the title of an infoWindow. The select box is intended to be populated with the list of identified results. I'm trying two different ways:
1) Adding the combobox declaratively using html:
var template = new esri.InfoTemplate(layerName + "<br/><select id="id_select" data-dojo-type="dijit/form/Select"</select>,"<br/> FID : ${FID}");
The combobox is there, but I don't know how to access the combobox to add the options dynamically (via addOptions). I would normally do dijit.byId("id_select"), but considering it doesn't exist until it's created...I'm not sure how to go about this way.
2) Programmatically
With the code below, the title displays information regarding the dijit/form/select widget (It displays: [object HTML TableElement]), but not the widget itself. Wondering if this can be rectified using dijitStartup(), but I can't haven't figured out how to use it (currently trying something along the lines of myTemplate.startupDijits(mySelectBox)--not with these variable names). I tried using domConstruct like this example
var identifyTask, identifyParams, idPoint;
var identifyResults;
require([
"esri/dijit/Popup",
"esri/tasks/IdentifyTask",
"esri/tasks/IdentifyParameters",
"dijit/form/Select",
"dojo/dom-construct",
"dojo/promise/all",
"dojo/domReady!"
], function (
Popup, IdentifyTask, IdentifyParameters, Select, domConstruct, All
) {
var identifySelect;
//dojo.connect(window.myMap, "onLoad", mapReady);
mapReady(window.myMap);
function mapReady(map) {
dojo.connect(window.myMap, "onClick", runIdentifies);
}
function runIdentifies(evt) {
identifyResults = [];
idPoint = evt.mapPoint;
var layers = dojo.map(window.myMap.layerIds, function (layerId) {
return window.myMap.getLayer(layerId);
});
layers = dojo.filter(layers, function (layer) {
if (layer.visibleLayers[0] !== -1) {
return layer.getImageUrl && layer.visible
}
}); //Only dynamic layers have the getImageUrl function. Filter so you only query visible dynamic layers
var tasks = dojo.map(layers, function (layer) {
return new IdentifyTask(layer.url);
}); //map each visible dynamic layer to a new identify task, using the layer url
var defTasks = dojo.map(tasks, function (task) {
return new dojo.Deferred();
}); //map each identify task to a new dojo.Deferred
var params = createIdentifyParams(layers, evt);
var promises = [];
for (i = 0; i < tasks.length; i++) {
promises.push(tasks[i].execute(params[i])); //Execute each task
}
var allPromises = new All(promises);
allPromises.then(function (r) { showIdentifyResults(r, tasks); });
}
function showIdentifyResults(r, tasks) {
var results = [];
var taskUrls = [];
var resultNames = [];
r = dojo.filter(r, function (result) {
return r[0];
});
for (i = 0; i < r.length; i++) {
results = results.concat(r[i]);
for (j = 0; j < r[i].length; j++) {
taskUrls = taskUrls.concat(tasks[i].url);
}
}
results = dojo.map(results, function (result, index) {
var feature = result.feature;
var layerName = result.layerName;
var serviceUrl = taskUrls[index];
resultNames.push({
value: result.layerName,
label: result.layerName
});
feature.attributes.layerName = result.layerName;
var identifiedList = getIdentifiedList(resultNames);
console.log(identifiedList);
var template = new esri.InfoTemplate();
template.setTitle(identifiedList);
feature.setInfoTemplate(template);
var resultGeometry = feature.geometry;
var resultType = resultGeometry.type;
return feature;
});
if (results.length === 0) {
window.myMap.infoWindow.clearFeatures();
} else {
window.myMap.infoWindow.setFeatures(results);
}
window.myMap.infoWindow.show(idPoint);
identifySelect.on('change', function(evt) {
var identIndex = identifySelect.get("value");
console.log(identIndex);
window.myMap.infoWindow.select(identIndex);
});
return results;
}
function getIdentifiedList(options) {
identifySelect = new Select({
name: "identifySelect",
id: "id_select",
options: options
}, domConstruct.create("select"));
return identifySelect.domNode;
}
function createIdentifyParams(layers, evt) {
var identifyParamsList = [];
identifyParamsList.length = 0;
dojo.forEach(layers, function (layer) {
var idParams = new esri.tasks.IdentifyParameters();
idParams.width = window.myMap.width;
idParams.height = window.myMap.height;
idParams.geometry = evt.mapPoint;
idParams.mapExtent = window.myMap.extent;
idParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;
var visLayers = layer.visibleLayers;
if (visLayers !== -1) {
var subLayers = [];
for (var i = 0; i < layer.layerInfos.length; i++) {
if (layer.layerInfos[i].subLayerIds == null)
subLayers.push(layer.layerInfos[i].id);
}
idParams.layerIds = subLayers;
} else {
idParams.layerIds = [];
}
idParams.tolerance = 5;
idParams.returnGeometry = true;
identifyParamsList.push(idParams);
});
return identifyParamsList;
}
});
Hi this is kinda old but i'll give it a shot. I hope this answers your question.
So if the problem is accessing the infoWindow what you need to do is set up a listener for when it is created.
on(map.infoWindow, "show", function () {
// do something
})
I have a fiddle that shows how to access infoWindow upon creation:
https://jsfiddle.net/kreza/jpLj5y4h/

Rxjs observing object updates and changes

I am currently trying to observe any changes to a given object including all of it's elements.
The following code only fires when an object[x] is updates, but not if individually updating object[x]'s elements such as object[x][y]
<script>
var elem = document.getElementById("test1");
var log = function(x) {
elem.innerHTML += x + "<br/><br/><br/>";
};
var a = [{a:1,b:2},
{a:2,b:5}
];
var source = Rx.Observable
.ofObjectChanges(a)
.map(function(x) {
return JSON.stringify(x);
});
var subscription = source.subscribe(
function (x) {log(x);},
function (err) {log(err);},
function () {log('Completed');}
);
a[0] = a[1];
</script>
This code runs and fires correctly.
however. if I instead to this
a[0]['a'] = 3;
Then nothing happens.
EDIT
A better way to phrase this, how can I observe changes from an array of objects?
If you want only the nested object changes:
var source = rx.Observable.from(a).flatMap(function(item) {
return rx.Observable.ofObjectChanges(item);
});
If you also want changes like a[0] = a[1]:
var source = rx.Observable.merge(
rx.Observable.ofArrayChanges(a),
rx.Observable.from(a).flatMap(function(item) {
return rx.Observable.ofObjectChanges(item);
})
);
The flatMap or selectMany (they are the same function) will allow you to iterate over a value and execute a function that returns an Observable. The values from all these Observables are "flattened" onto a new stream that is returned.
http://reactivex.io/documentation/operators/flatmap.html
Perhaps something like this by merging two Observables (one for the array and the other observing the elements of the array):
var a = [
{a:1,b:2},
{a:2,b:5}
];
var source1 = Rx.Observable.ofArrayChanges(a).map(function(x) {
return JSON.stringify(x);
});
var source2 = Rx.Observable
.fromArray(a.map(function(o, i) { return [o, i]; }))
.flatMap(function(oi) {
return Rx.Observable.ofObjectChanges(oi[0])
.map(function(x) {
var y = {
type: x.type,
object: x.object,
name: x.name,
oldValue: x.oldValue,
arrayIndex: oi[1] // pass the index of the member that changed
};
return JSON.stringify(y);
});
})
source = source1.merge(source2)
var subscription = source.subscribe(
function (x) {log(x);},
function (err) {log(err);},
function () {log('Completed');}
);
a[0] = a[1]
a[1]['b'] = 7
Thanks to #electrichead here we're not using concatMap because the sources that we made by ofObjectChanges and ofArrayChanges never complete.
Here's a working example of Rx.Observable.ofNestedObjectChanges simple implementation, you can get the gist of it and implement you own.
http://jsbin.com/wekote/edit?js,console
Rx.Observable.ofNestedObjectChanges = function(obj) {
if (obj == null) { throw new TypeError('object must not be null or undefined.'); }
if (typeof Object.observe !== 'function' && typeof Object.unobserve !== 'function') { throw new TypeError('Object.observe is not supported on your platform') }
return new Rx.AnonymousObservable(function(observer) {
function observerFn(changes) {
for(var i = 0, len = changes.length; i < len; i++) {
observer.onNext(changes[i]);
}
}
Object.observe(obj, observerFn);
//Recursive observers hooks - same observerFn
traverseObjectTree(obj, observerFn);
function traverseObjectTree(element, observerFn){
for(var i=0;i<Object.keys(element).length;i++){
var myObj = element[Object.keys(element)[i]];
if(typeof myObj === "object"){
Object.observe(myObj, observerFn);
traverseObjectTree(myObj,observerFn);
}
}
}
return function () {
Object.unobserve(obj, observerFn);
};
});
};
//Test
var json = {
element : {
name : "Yocto",
job : {
title: "Designer"
}
},
element1: {
name : "Mokto"
}
};
setTimeout(function(){
json.element.job.title = "A Great Designer";
},3000);
var source = Rx.Observable.ofNestedObjectChanges(json);
var subscription = source.subscribe(
function (x) {
console.log(x);
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
json.element.name = "Candy Joe";

A Javascript function which creates an object which calls the function itself

I am trying to make an angular service that returns a new object.
That's fine and good and works. new MakeRoll() creates an instance. But self.add, near the end also calls new MakeRoll() and that doesn't create an instance when I call add like I think it should.
I'm probably doing this all wrong but I haven't been able to figure it out.
var services = angular.module('services', []);
services.factory('Roll', [function() {
var MakeRoll = function () {
var self = {};
self.rolls = [];
self.add = function(number, sizeOfDice, add) {
var newRoll = {};
newRoll.number = number || 1;
newRoll.sizeOfDice = sizeOfDice || 6;
newRoll.add = add || 0;
newRoll.rollDice = function() {
var result = 0;
var results=[];
for (var i = 0; i < newRoll.number; i++) {
var roll = Math.floor(Math.random() * newRoll.sizeOfDice) + 1;
result += roll;
results.push(roll);
}
newRoll.results = results;
newRoll.result = result;
newRoll.Roll = new MakeRoll();
};
self.rolls.push(newRoll);
return self;
};
self.remove = function(index) {
self.rolls.splice(index, 1);
};
self.get = function(index) {
return self.rolls[index];
};
return self;
};
return new MakeRoll();
}
]);
angular service is designed to be singleton to accomplish some business logic, so don't mix up plain model with angular service. if you want to have more objects, just create a constructor and link it in service to be operated on.
function MakeRoll() {
...
}
angular.module('service', []).factory('Roll', function () {
var rolls = [];
return {
add: add,
remove: remove,
get: get
}
function add() {
// var o = new MakrRoll();
// rolls.push(o);
}
function remove(o) {
// remove o from rolls
}
function get(o) {
// get o from rolls
}
});

Categories

Resources