Overloading operators in classes - javascript

example:
class GameObjectList {
#list;
constructor() {
/** #member {GameObject[]} */
this.#list = [];
}
/**
* #param {GameObject} object
* #returns {boolean} true if added
*/
push(object) {
if( !(object instanceof GameObject) )
return false;
for (var i = 0; i < this.#list.length; ++i) {
if (this.#list[i] == object)
{
return false;
}
}
this.#list.push(object);
return true;
}
}
Is there any way operator [] executed on GameObjectList would return nth object of #list?
let list= new GameObjectList();
let objA = new GameObject();
let objB = new GameObject();
let objC = new GameObject();
list.push(objA);
list.push(objB);
list.push(objC);
list[1] // returns objB
Or if it is impossible what is best practise to replace it?

Related

Javascript json add a child element dynamically [duplicate]

Suppose we are only given
var obj = {};
var propName = "foo.bar.foobar";
How can we set the property obj.foo.bar.foobar to a certain value (say "hello world")?
So I want to achieve this, while we only have the property name in a string:
obj.foo.bar.foobar = "hello world";
function assign(obj, prop, value) {
if (typeof prop === "string")
prop = prop.split(".");
if (prop.length > 1) {
var e = prop.shift();
assign(obj[e] =
Object.prototype.toString.call(obj[e]) === "[object Object]"
? obj[e]
: {},
prop,
value);
} else
obj[prop[0]] = value;
}
var obj = {},
propName = "foo.bar.foobar";
assign(obj, propName, "Value");
I know it's an old one, but I see only custom functions in answers.
If you don't mind using a library, look at lodash _.set and _.get function.
Since this question appears to be answered by incorrect answers, I'll just refer to the correct answer from a similar question
function setDeepValue(obj, value, path) {
if (typeof path === "string") {
var path = path.split('.');
}
if(path.length > 1){
var p=path.shift();
if(obj[p]==null || typeof obj[p]!== 'object'){
obj[p] = {};
}
setDeepValue(obj[p], value, path);
}else{
obj[path[0]] = value;
}
}
Use:
var obj = {};
setDeepValue(obj, 'Hello World', 'foo.bar.foobar');
edit: I've created a jsPerf.com testcase to compare the accepted answer with my version.
Turns out that my version is faster, especially when you go very deep.
http://jsfiddle.net/9YMm8/
var nestedObjectAssignmentFor = function(obj, propString, value) {
var propNames = propString.split('.'),
propLength = propNames.length-1,
tmpObj = obj;
for (var i = 0; i <= propLength ; i++) {
tmpObj = tmpObj[propNames[i]] = i !== propLength ? {} : value;
}
return obj;
}
var obj = nestedObjectAssignment({},"foo.bar.foobar","hello world");
​
​
All solutions overid any of the original data when setting so I have tweaked with the following, made it into a single object too:
var obj = {}
nestObject.set(obj, "a.b", "foo");
nestObject.get(obj, "a.b"); // returns foo
var nestedObject = {
set: function(obj, propString, value) {
var propNames = propString.split('.'),
propLength = propNames.length-1,
tmpObj = obj;
for (var i = 0; i <= propLength ; i++) {
if (i === propLength){
if(tmpObj[propNames[i]]){
tmpObj[propNames[i]] = value;
}else{
tmpObj[propNames[i]] = value;
}
}else{
if(tmpObj[propNames[i]]){
tmpObj = tmpObj[propNames[i]];
}else{
tmpObj = tmpObj[propNames[i]] = {};
}
}
}
return obj;
},
get: function(obj, propString){
var propNames = propString.split('.'),
propLength = propNames.length-1,
tmpObj = obj;
for (var i = 0; i <= propLength ; i++) {
if(tmpObj[propNames[i]]){
tmpObj = tmpObj[propNames[i]];
}else{
break;
}
}
return tmpObj;
}
};
Can also change functions to be an Oject.prototype method changing obj param to this:
Object.prototype = { setNested = function(){ ... }, getNested = function(){ ... } }
{}.setNested('a.c','foo')
Here is a get and set function i just compiled from a couple of threads + some custom code.
It will also create keys that don't exist on set.
function setValue(object, path, value) {
var a = path.split('.');
var o = object;
for (var i = 0; i < a.length - 1; i++) {
var n = a[i];
if (n in o) {
o = o[n];
} else {
o[n] = {};
o = o[n];
}
}
o[a[a.length - 1]] = value;
}
function getValue(object, path) {
var o = object;
path = path.replace(/\[(\w+)\]/g, '.$1');
path = path.replace(/^\./, '');
var a = path.split('.');
while (a.length) {
var n = a.shift();
if (n in o) {
o = o[n];
} else {
return;
}
}
return o;
}
Here is a simple function to do that using reference.
function setValueByPath (obj, path, value) {
var ref = obj;
path.split('.').forEach(function (key, index, arr) {
ref = ref[key] = index === arr.length - 1 ? value : {};
});
return obj;
}
You could split the path and make a check if the following element exist. If not assign an object to the new property.
Return then the value of the property.
At the end assign the value.
function setValue(object, path, value) {
var fullPath = path.split('.'),
way = fullPath.slice(),
last = way.pop();
way.reduce(function (r, a) {
return r[a] = r[a] || {};
}, object)[last] = value;
}
var object = {},
propName = 'foo.bar.foobar',
value = 'hello world';
setValue(object, propName, value);
console.log(object);
Here's one that returns the updated object
function deepUpdate(value, path, tree, branch = tree) {
const last = path.length === 1;
branch[path[0]] = last ? value : branch[path[0]];
return last ? tree : deepUpdate(value, path.slice(1), tree, branch[path[0]]);
}
const path = 'cat.dog';
const updated = deepUpdate('a', path.split('.'), {cat: {dog: null}})
// => { cat: {dog: 'a'} }
A very straightforward one.
This implementation should be very performant.
It avoids recursions, and function calls, while maintaining simplicity.
/**
* Set the value of a deep property, creating new objects as necessary.
* #param {Object} obj The object to set the value on.
* #param {String|String[]} path The property to set.
* #param {*} value The value to set.
* #return {Object} The object at the end of the path.
* #author github.com/victornpb
* #see https://stackoverflow.com/a/46060952/938822
* #example
* setDeep(obj, 'foo.bar.baz', 'quux');
*/
function setDeep(obj, path, value) {
const props = typeof path === 'string' ? path.split('.') : path;
for (var i = 0, n = props.length - 1; i < n; ++i) {
obj = obj[props[i]] = obj[props[i]] || {};
}
obj[props[i]] = value;
return obj;
}
/*********************** EXAMPLE ***********************/
const obj = {
hello : 'world',
};
setDeep(obj, 'root', true);
setDeep(obj, 'foo.bar.baz', 1);
setDeep(obj, ['foo','quux'], '😉');
console.log(obj);
// ⬇︎ Click "Run" below to see output
I was looking for an answer that does not overwrite existing values and was easily readable and was able to come up with this. Leaving this here in case it helps others with the same needs
function setValueAtObjectPath(obj, pathString, newValue) {
// create an array (pathComponents) of the period-separated path components from pathString
var pathComponents = pathString.split('.');
// create a object (tmpObj) that references the memory of obj
var tmpObj = obj;
for (var i = 0; i < pathComponents.length; i++) {
// if not on the last path component, then set the tmpObj as the value at this pathComponent
if (i !== pathComponents.length-1) {
// set tmpObj[pathComponents[i]] equal to an object of it's own value
tmpObj[pathComponents[i]] = {...tmpObj[pathComponents[i]]}
// set tmpObj to reference tmpObj[pathComponents[i]]
tmpObj = tmpObj[pathComponents[i]]
// else (IS the last path component), then set the value at this pathComponent equal to newValue
} else {
// set tmpObj[pathComponents[i]] equal to newValue
tmpObj[pathComponents[i]] = newValue
}
}
// return your object
return obj
}
Same as Rbar's answers, very useful when you're working with redux reducers. I use lodash clone instead of spread operator to support arrays too:
export function cloneAndPatch(obj, path, newValue, separator='.') {
let stack = Array.isArray(path) ? path : path.split(separator);
let newObj = _.clone(obj);
obj = newObj;
while (stack.length > 1) {
let property = stack.shift();
let sub = _.clone(obj[property]);
obj[property] = sub;
obj = sub;
}
obj[stack.shift()] = newValue;
return newObj;
}
Object.getPath = function(o, s) {
s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
s = s.replace(/^\./, ''); // strip a leading dot
var a = s.split('.');
for (var i = 0, n = a.length; i < n; ++i) {
var k = a[i];
if (k in o) {
o = o[k];
} else {
return;
}
}
return o;
};
Object.setPath = function(o, p, v) {
var a = p.split('.');
var o = o;
for (var i = 0; i < a.length - 1; i++) {
if (a[i].indexOf('[') === -1) {
var n = a[i];
if (n in o) {
o = o[n];
} else {
o[n] = {};
o = o[n];
}
} else {
// Not totaly optimised
var ix = a[i].match(/\[.*?\]/g)[0];
var n = a[i].replace(ix, '');
o = o[n][ix.substr(1,ix.length-2)]
}
}
if (a[a.length - 1].indexOf('[') === -1) {
o[a[a.length - 1]] = v;
} else {
var ix = a[a.length - 1].match(/\[.*?\]/g)[0];
var n = a[a.length - 1].replace(ix, '');
o[n][ix.substr(1,ix.length-2)] = v;
}
};
Here's a simple method that uses a scoped Object that recursively set's the correct prop by path.
function setObjectValueByPath(pathScope, value, obj) {
const pathStrings = pathScope.split('/');
obj[pathStrings[0]] = pathStrings.length > 1 ?
setObjectValueByPath(
pathStrings.splice(1, pathStrings.length).join('/'),
value,
obj[pathStrings[0]]
) :
value;
return obj;
}
How about a simple and short one?
Object.assign(this.origin, { [propName]: value })
You can use reduce : (you can test it by copy/paste on browser console)
const setValueOf = (obj, value, ...path) => {
path.reduce((o, level, idx) => {
if(idx === path.length -1) { o[level] = value }; // on last change the value of the prop
return o && o[level]; // return the prop
}, obj);
};
Example
let objExmp = {a: 'a', b: {b1: 'b1', b2: 'b2', b3: { b3_3 : 'default_value' } }};
setValueOf(objExmp, 'new_value' , 'b', 'b3', 'b3_3');
console.log('objExmp', objExmp); // prop changed to 'new_value'
You can split the string path by '.' and spread like :
setValueOf(objExmp, 'new_value' , ...'b.b3.b3_3'.split('.'));

JavaScript: Convert dot notation string to array [duplicate]

I'm trying to create a JS object dynamically providing a key and a value. The key is in dot notation, so if a string like car.model.color is provided the generated object would be:
{
car: {
model: {
color: value;
}
}
}
The problem has a trivial solution if the key provided is a simple property, but i'm struggling to make it work for composed keys.
My code:
function (key, value) {
var object = {};
var arr = key.split('.');
for(var i = 0; i < arr.length; i++) {
object = object[arr[i]] = {};
}
object[arr[arr.length-1]] = value;
return object;
}
your slightly modified code
function f(key, value) {
var result = object = {};
var arr = key.split('.');
for(var i = 0; i < arr.length-1; i++) {
object = object[arr[i]] = {};
}
object[arr[arr.length-1]] = value;
return result;
}
In the loop you should set all of the props but the last one.
Next set the final property and all set.
If you're using lodash you could use _.set(object, path, value)
const obj = {}
_.set(obj, "car.model.color", "my value")
console.log(obj)
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
Use namespace pattern, like the one Addy Osmani shows: http://addyosmani.com/blog/essential-js-namespacing/
Here's the code, pasted for convenience, all credit goes to Addy:
// top-level namespace being assigned an object literal
var myApp = myApp || {};
// a convenience function for parsing string namespaces and
// automatically generating nested namespaces
function extend( ns, ns_string ) {
var parts = ns_string.split('.'),
parent = ns,
pl, i;
if (parts[0] == "myApp") {
parts = parts.slice(1);
}
pl = parts.length;
for (i = 0; i < pl; i++) {
//create a property if it doesnt exist
if (typeof parent[parts[i]] == 'undefined') {
parent[parts[i]] = {};
}
parent = parent[parts[i]];
}
return parent;
}
// sample usage:
// extend myApp with a deeply nested namespace
var mod = extend(myApp, 'myApp.modules.module2');
function strToObj(str, val) {
var i, obj = {}, strarr = str.split(".");
var x = obj;
for(i=0;i<strarr.length-1;i++) {
x = x[strarr[i]] = {};
}
x[strarr[i]] = val;
return obj;
}
usage: console.log(strToObj("car.model.color","value"));
I would use a recursive method.
var createObject = function(key, value) {
var obj = {};
var parts = key.split('.');
if(parts.length == 1) {
obj[parts[0]] = value;
} else if(parts.length > 1) {
// concat all but the first part of the key
var remainingParts = parts.slice(1,parts.length).join('.');
obj[parts[0]] = createObject(remainingParts, value);
}
return obj;
};
var simple = createObject('simple', 'value1');
var complex = createObject('more.complex.test', 'value2');
console.log(simple);
console.log(complex);
(check the console for the output)
Here's a recursive approach to the problem:
const strToObj = (parts, val) => {
if (!Array.isArray(parts)) {
parts = parts.split(".");
}
if (!parts.length) {
return val;
}
return {
[parts.shift()]: strToObj(parts, val)
};
}

Javascript new array prototype in new object constructor

If I do:
Array.prototype.test = "test"
Array.prototype.t = function() {return "hello"}
Every new Array will have the property test and the method t.
How can I do the same without affecting all Arrays?
Like:
Names = function(arr){
// Contacts constructor must be the same of Array
// but add the property test and the function t
}
z=new Names(["john","andrew"])
So that z.test will return "test" and z.t() will return "hello"?
(but Array.test and Array.t would stay undefined)
I explain better:
Array.prototype.t="test";
Array.prototype.test = function(){ return "hello";}
z=new Array("john", "andrew")
console.log(z);
But this affects ALL arrays.
I want the same but with a new constructor Names that inherits Array constructor.
class Names extends Array {
constructor(...args) {
super(...args);
}
}
Names.prototype.t = 'test';
let z = new Names("john", "andrew")
z.push('Amanda')
console.log(z.t)
console.log(z)
You can easily set it at Names.prototype
Can't you just extend Array?
class Names extends Array {
constructor(...args) {
super(...args);
this.t = "test";
}
test() { return "hello" }
}
let z = new Names("john", "andrew")
Here is a crude implementation:
function Names(arr) {
this.contacts = enhanceArray(arr);
}
function enhanceArray(arr) {
arr.test = 'helloProp';
arr.t = function() {
return 'helloFunc'
}
return arr;
}
let z = new Names(["john", "andrew"]);
console.log(z.contacts[0]);
console.log(z.contacts.test);
console.log(z.contacts.t());
You can create your own extended Array constructor factory, something like
(() => {
const myArr = XArray();
let a = myArr(["John", "Mary", "Michael"]);
console.log(`myArr(["John", "Mary", "Michael"]).sayHi(1): ${a.sayHi(1)}`);
console.log("demo: myArr(1, 2, 3) throws an error");
let b = myArr(1, 2, 3); // throws
// an extended array
function XArray() {
const Arr = function(arr) {
if (arr.constructor !== Array) {
throw new TypeError("Expected an array");
}
this.arr = arr;
};
Arr.prototype = {
sayHi: function (i) { return `hi ${this.arr[i]}`; }
};
return arr => new Arr(arr);
}
})();

How to retrieve all the data/words in a radix trie in Javascript

I've been able to cook up a Radix tree example in JavaScript (not optimised, so don't judge)
So far I have been able to Add, Transverse and Find nodes.
I'm having trouble writing a function that can retrieve all nodes, this is where I require assistance.Thank you in advance
// As illustrated in:
// http://programminggeeks.com/c-code-for-radix-tree-or-trie/
// Make a class of the Tree so that you can define methods all nodes of the tree
// which are actually Trees in structure inherit the functions
function Tree() {
this.character = undefined;
// if this node is the end of a complete word
// this was we can differentiate "sell" and "sells" if both are searched for
this.isword = false;
// How to nest the nodes, thus creating a tree structure
this.node = {}; // [new Tree(), new Tree(), new Tree()];
// abcdefghijklmnopqrstuvwxyz
var start = 97,
end = start + 25;
function constructor(that) {
for (var x = start; x <= end; x++) {
// for now they are all unsigned objects
that.node[x] = null // new Tree()
}
return that;
}
constructor(this);
return this;
}
Tree.prototype.addNode = function(word) {
return this.transverseNodes(word, true);
};
Tree.prototype.searchForNodes = function(word) {
return this.transverseNodes(word, false);
};
Tree.prototype.stringToNodes = function(word) {
var nodeArray = []
for (var x = 0, length = word.length; x < length; x++) {
nodeArray.push(word.charCodeAt(x));
}
return nodeArray;
};
Tree.prototype.transverseNodes = function(word, bool) {
// make all of the letters lowercase to create uniformity
var nodes = this.stringToNodes(word.toLowerCase());
// console.log(nodes);
// start with parent/root tree
var currentTreeNode = this
// transverse checking if node has been added, if not add it
// if it was already added and it terminates a word set it "isword" property to true
for (var i = 0, length = nodes.length; i < length; i++) {
var node = nodes[i];
// If the current tree node is defined so not overwrite it
if (currentTreeNode.node[node] === null) {
if (!bool) {
// if bool is undefined of false, then this is a search
return false;
}
// create a node
currentTreeNode.node[node] = new Tree();
currentTreeNode.node[node].character = String.fromCharCode(node);
}
// check if the node is the last character of the word
if ((nodes.length - 1) === i) {
// console.log(nodes.length - 1, i)
if (!bool) {
// if bool is undefined of false, then this is a search
return true;
}
currentTreeNode.node[node].isword = true;
}
// get into the nested node
currentTreeNode = currentTreeNode.node[node];
};
return this;
};
var tree = new Tree()
// Create the nodes
tree.addNode("cat");
tree.addNode("camel");
tree.addNode("condom");
tree.addNode("catastrophe");
tree.addNode("grandma");
tree.addNode("lamboghini");
// Search the nodes
console.log(tree.searchForNodes("cat")); // true
console.log(tree.searchForNodes("catapult")); // false
console.log(tree.searchForNodes("catastrophe")); // true
console.log(tree.searchForNodes("mama")); // false
console.log(tree.searchForNodes("lamboghini")); // true
// retrieving all node
// console.log(tree.retrieveAllNodes());
This proposal features an iterative and recursive approach for getting the words in the tree.
'use strict';
// As illustrated in:
// http://programminggeeks.com/c-code-for-radix-tree-or-trie/
// Make a class of the Tree so that you can define methods all nodes of the tree
// which are actually Trees in structure inherit the functions
function Tree() {
this.character = undefined;
// if this node is the end of a complete word
// this was we can differentiate "sell" and "sells" if both are searched for
this.isword = false;
// How to nest the nodes, thus creating a tree structure
this.node = {}; // [new Tree(), new Tree(), new Tree()];
// abcdefghijklmnopqrstuvwxyz
var start = 97,
end = start + 25;
function constructor(that) {
for (var x = start; x <= end; x++) {
// for now they are all unsigned objects
that.node[x] = null // new Tree()
}
return that;
}
constructor(this);
return this;
}
Tree.prototype.addNode = function (word) {
return this.transverseNodes(word, true);
};
Tree.prototype.searchForNodes = function (word) {
return this.transverseNodes(word, false);
};
Tree.prototype.stringToNodes = function (word) {
var nodeArray = []
for (var x = 0, length = word.length; x < length; x++) {
nodeArray.push(word.charCodeAt(x));
}
return nodeArray;
};
Tree.prototype.transverseNodes = function (word, bool) {
// make all of the letters lowercase to create uniformity
var nodes = this.stringToNodes(word.toLowerCase());
// console.log(nodes);
// start with parent/root tree
var currentTreeNode = this
// transverse checking if node has been added, if not add it
// if it was already added and it terminates a word set it "isword" property to true
for (var i = 0, length = nodes.length; i < length; i++) {
var node = nodes[i];
// If the current tree node is defined so not overwrite it
if (currentTreeNode.node[node] === null) {
if (!bool) {
// if bool is undefined of false, then this is a search
return false;
}
// create a node
currentTreeNode.node[node] = new Tree();
currentTreeNode.node[node].character = String.fromCharCode(node);
}
// check if the node is the last character of the word
if ((nodes.length - 1) === i) {
// console.log(nodes.length - 1, i)
if (!bool) {
// if bool is undefined of false, then this is a search
return true;
}
currentTreeNode.node[node].isword = true;
}
// get into the nested node
currentTreeNode = currentTreeNode.node[node];
};
return this;
};
Tree.prototype.retrieveAllNodes = function () {
// function for traversing over object, takes the object and an empty string for
// the appearing words, acts as closure for the object
function iterObject(o, r) {
// how i like to start functions with return (...)
// returns basically the up coming word.
// reason for reduce, this provides a return value, with the letters
// of the path
return Object.keys(o).reduce(function (r, key) {
// check if the key property has a truthy value (remember the default
// null values)
if (o[key]) {
// if so, check the property isword
if (o[key].isword) {
// if its truty here, we have a hit, a word is found
wordList.push(r + o[key].character);
};
// check for children
if (o[key].node) {
// if node exist, go on with a new iteration and a new word
// extension
iterObject(o[key].node, r + o[key].character);
}
}
// return the inevitable word stem
return r;
}, r);
}
var wordList = [];
iterObject(this.node, '');
return wordList;
}
var tree = new Tree();
// Create the nodes
tree.addNode("cat");
tree.addNode("camel");
tree.addNode("condom");
tree.addNode("catastrophe");
tree.addNode("grandma");
tree.addNode("lamboghini");
// Search the nodes
console.log(tree.searchForNodes("cat")); // true
console.log(tree.searchForNodes("catapult")); // false
console.log(tree.searchForNodes("catastrophe")); // true
console.log(tree.searchForNodes("mama")); // false
console.log(tree.searchForNodes("lamboghini")); // true
// retrieving all words
console.log(JSON.stringify(tree.retrieveAllNodes(), 0, 4));
// retrieving whole tree
console.log(JSON.stringify(tree, 0, 4));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Bonus: Below is a version with very small overhead.
'use strict';
function Tree() {
return this;
}
Tree.prototype.addNode = function (word) {
this.stringToNodes(word).reduce(function (node, character, i, a) {
if (!node[character]) {
node[character] = {};
}
if (i === a.length - 1) {
node[character].isword = true;
}
return node[character];
}, this);
return this;
};
Tree.prototype.searchForNodes = function (word) {
function iterObject(o, r) {
return Object.keys(o).reduce(function (r, key) {
if (key === 'isword' && r === word) {
found = true;
}
typeof o[key] === 'object' && iterObject(o[key], r + key);
return r;
}, r);
}
var found = false;
iterObject(this, '');
return found;
};
Tree.prototype.stringToNodes = function (word) {
return word.toLowerCase().split('');
};
Tree.prototype.retrieveAllNodes = function () {
function iterObject(o, r) {
return Object.keys(o).reduce(function (r, key) {
key === 'isword' && wordList.push(r);
typeof o[key] === 'object' && iterObject(o[key], r + key);
return r;
}, r);
}
var wordList = [];
iterObject(this, '');
return wordList;
}
var tree = new Tree();
// Create the nodes
tree.addNode("cat");
tree.addNode("camel");
tree.addNode("condom");
tree.addNode("catastrophe");
tree.addNode("grandma");
tree.addNode("lamboghini");
// Search the nodes
console.log(tree.searchForNodes("cat")); // true
console.log(tree.searchForNodes("catapult")); // false
console.log(tree.searchForNodes("catastrophe")); // true
console.log(tree.searchForNodes("mama")); // false
console.log(tree.searchForNodes("lamboghini")); // true
// retrieving all words
console.log(JSON.stringify(tree.retrieveAllNodes(), 0, 4));
// retrieving whole tree
console.log(JSON.stringify(tree, 0, 4));
.as-console-wrapper { max-height: 100% !important; top: 0; }
I'm not sure if you're doing that for studying, but if not, I suggest you to not reinvent the wheel, and try some library that already exists for that purpose, e.g. Javid Jamae's RadixTreeJS.

how to remove an item in a javascript array with json form

i have this json structure and I made it into an array. I was trying to remove the entry, but this code failed on me: Remove item from array if it exists in a 'disallowed words' array
var historyList = []; // assuming this already has the array filled
function add() {
var newHistory = {
ID: randomString(),
Name: $('#txtVaccineName').val(),
DoseDate: doseDate,
ResultDate: resultDate,
Notes: $('#txtResultNotes').val()
};
historyList.push(newHistory);
};
function removeEntry(value) {
historyList.remove('ID', value);
};
Array.prototype.remove = function(name, value) {
array = this;
var rest = $.grep(this, function(item) {
return (item[name] != value);
});
array.length = rest.length;
$.each(rest, function(n, obj) {
array[n] = obj;
});
};
You could use a property filter to match the item in your history list. Below is the sample quick code to do so, I've modified your history list a bit.
A quick test in FF, shows that it works!
var historyList = []; // assuming this already has the array filled
function addToHistory(name, notes) {
var newHistory = {
ID: new Date().getTime(),
Name: name,
DoseDate: "Somedate",
ResultDate: "SomeResultDate",
Notes: notes,
toString: function() {return this.Name;}
};
historyList.push(newHistory);
};
var Util = {};
/**
* Gets the index if first matching item in an array, whose
* property (specified by name) has the value specified by "value"
* #return index of first matching item or false otherwise
*/
Util.arrayIndexOf = function(arr, filter) {
for(var i = 0, len = arr.length; i < len; i++) {
if(filter(arr[i])) {
return i;
}
}
return -1;
};
/**
* Matches if the property specified by pName in the given item,
* has a value specified by pValue
* #return true if there is a match, false otherwise
*/
var propertyMatchFilter = function(pName, pValue) {
return function(item) {
if(item[pName] === pValue) {
return true;
}
return false;
}
}
/**
* Remove from history any item whose property pName has a value
* pValue
*/
var removeHistory = function(pName, pValue) {
var nameFilter = propertyMatchFilter(pName, pValue);
var idx = Util.arrayIndexOf(historyList, nameFilter);
if(idx != -1) {
historyList.splice(idx, 1);
}
};
// ---------------------- Tests -----------------------------------
addToHistory("history1", "Note of history1");
addToHistory("history2", "Note of history2");
addToHistory("history3", "Note of history3");
addToHistory("history4", "Note of history4");
alert(historyList); // history1,history2,history3,history4
removeHistory("Name", "history1");
alert(historyList); // history2,history3,history4
removeHistory("Notes", "Note of history3");
alert(historyList); // history2,history4
The entire Array.prototype.remove function can be inlined as follows:
function removeEntry(value) {
historyList = $.grep(historyList, function(item) {
return (item.ID !== value);
});
}
You can, of course, create a function to wrap $.grep or the predicate as you wish. (And if you do, you probably don't want to modify Array.prototype; prefer modifying historyList itself (using Array.prototype.splice) or creating a (likely static) function elsewhere.)
Also, this problem does not relate to the SO question you mention in your question, as far as I can tell.

Categories

Resources