My array looks like this:
"MODE:ID:A:B"
["add:123456789:0:0", "del:99887766:0:0", "edit:1471872633890:8845:0", "add:4875125862:1523:NE"]
When a user deletes a row from a table a del entry is added to the array.
If the user has added a new entry to the table a add entry is added to the array.
If the user edits an entry an edit entry is added to the array.
The issue I have is if the user adds and then deletes the same row, I end up with two entries:
["add:123456789:0:0", "del:123456789:0:0"]
How can I get the del to overwrite the add (and/or) edit entry matching on the ID ?
I've tried:
rows = rows.map(function(value) {
if( value.indexOf(id) > -1 ) {
return false;
}
return value;
});
but that just replaces the entry with 'false' it doesn't delete it.
Any idea how I can do this ?
Thanks
jQuery.map will work as you expect. undefined or null return values will not be mapped.
rows = $.map(rows, function(value) {
if( value.indexOf(id) > -1 ) {
return undefined;
}
return value;
});
jQuery map callback function can return:
the translated value, which will be mapped to the resulting array
null or undefined, to remove the item
an array of values, which will
be flattened into the full array
You could iterate the array and split an item for the check and update and reassemble the item for an assingment to the element.
This proposal expects only one item with the given id.
var data = ["add:123456789:0:0", "del:99887766:0:0", "edit:1471872633890:8845:0", "add:4875125862:1523:NE"],
id = '123456789';
data.some(function (a, i, aa) {
var item = a.split(':')
if (item[1] === id) {
item[0] = "del";
aa[i] = item.join(':');
return true;
}
});
console.log(data);
You can just add a filter in the end:
rows = rows.map(function(value) {
if( value.indexOf(id) > -1 ) {
return false;
}
return value;
})
.filter( function(item) {return item;});
Try using this
rows = $.map(rows, function(value){
if(value.indexOf(id) > -1){
return 'del:' + id;
}
}
Related
I want to return multiple values from for loop and if my condition satisfies more than one time
for(var i=0;i<graphVariableCount;i++)
{
if(commandResponse.GenericName == graphVariables[i].variable.index)
{
return graphVariables[i].variable.index;
}
}
In above code i am able to return only one value. If GenericName of graphVariable[i].variable.index is same for 4-5 variables. Then how am i able to return that values.
Use filter and map
return graphVariables.filter( s => commandResponse.GenericName == s.variable.index )
.map( s => s.variable.index );
Explanation
filter will filter the array to get only matching values
map will iterate that filtered array and get only s.variable.index from the same.
var values = [];
for(var i=0;i<graphVariableCount;i++)
{
if(commandResponse.GenericName == graphVariables[i].variable.index)
{
values.push(graphVariables[i].variable.index);
}
}
return values;
You can use temperory as below:
var results= [];
for(var i=0;i<graphVariableCount;i++)
{
if(commandResponse.GenericName == graphVariables[i].variable.index)
{
results.push( graphVariables[i].variable.index);
}
}
I'd like to remove multiple specific elements from my array before it displays. Here is the code I have but it results in none of the elements being displayed:
$('[data-fancybox]').on('click', function() {
var visibleLinks = $('.fancybox:visible');
$.fancybox.open( visibleLinks, {
//options go here
caption: function (instance, item) {
var caption, link, collectTags, tags, filterTags, filteredTags;
function format(tpl, binding) {
if (typeof binding != 'function') return format(tpl, function (_, name) {
return binding[name];
});
return tpl.replace(/\$(\w+)/g, binding);
}
caption = $(this).data('caption');
link = format('<br>See more pictures', item);
collectTags = $(this).parent().attr("class").split(' ');
function createTag(it) {
return format("<a href='$site$it'>$it</a>", {
site: (it == 'wedding' || it == 'concert') ? 'http://example.com/gallery/#filter=.' : 'http://example.com/gallery/#filter=.',
it: it
});
}
filterTags = ['churchevent', 'corporate'];
filteredTags = tags.filter(function(itm){return itm!== filterTags});
tags = $.map(collectTags, createTag);
return [].concat(caption ? [caption, link] : link).concat(filteredTags.slice(1).join(', ')).join('<br>');
}
}, visibleLinks.index( this ) );
return false;
});
I'm supposing that, since you wrote "remove multiple specific elements" you want to REMOVE filterTags.
If that's the case then change this:
filterTags = ['churchevent', 'corporate'];
filteredTags = tags.filter(function(itm){return itm!== filterTags});
tags = $.map(collectTags, createTag);
return [].concat(caption ? [caption, link] : link).concat(filteredTags.slice(1).join(', ')).join('<br>');
to this:
filterTags = ['churchevent', 'corporate'];
tags = $.map(collectTags, createTag);
filteredTags = tags.filter((item)=>{
for(tag in filterTags) if (item.indexOf(filterTags[tag]) != -1) return false;
return true;
});
return [].concat(caption ? [caption, link] : link).concat(filteredTags.slice(1).join(', ')).join('<br>');
else just use != -1 instead of == -1 in the filter method.
What is "tags" in the context of tags.filter? I'm assuming it is some array. In either case, your filter is checking that an item in tags is not equal to filterTags, an array. Of course a single item in an array won't be equal to an array, so this will always return true, thus not filtering anything.
I think you probably want something like:
filteredTags = tags.filter(function(itm){return filterTags.indexOf(itm) !== -1});
Are you speaking about this array?
filterTags = ['churchevent', 'corporate'];
filteredTags = tags.filter(function(itm){return itm!== filterTags});
// Of note, you are creating tags just below this code. Should you move it up?
// Or rename tags => collectionTags???
// Either way, the filter function you are using is not doing what you expect.
tags.filter(function(itm){
// itm will be whatever, I'm guessing a string of some sort like "churchevent"
// Now you are trying to compare a string like "churchevent" to the
// array filterTags.
// This is what is happening...
return itm !== ['churchevent', 'corporate'];
// What you want to do is this in ES5
return (filterTags.indexOf(itm) === -1);
// or this in ES6
return !filterTags.includes(itm);
// Note the bang in front.
// TRUE will put itm in the tags array, FALSE will not.
}
Also, please reference the filter function in MDN.
Filter Function (MDN)
Here is the scenario:
There is a parameter titledlistOfSelectedProductIdsthat contains
all of the selected ids.
There is another list titled listOfAllPossibleProducts, which
contains a list of objects. That object contains a ProductId,
ProductName, and ProductCode. It looks something like this:
The task at hand:
I need to loop through my listOfSelectedProductIds. If the ProductId matches a ProductId from listOfAllPossibleProducts, then I need to return that object.
Here is what I am doing:
function SelectedProducts(listOfSelectedProductIds){
for (var index = 0; index < listOfSelectedProductIds.length; index++) {
var currentItem = listOfSelectedProductIds[index];
var desiredProduct = _.contains(listOfAllPossibleProducts, currentItem);
if (desiredProduct === true) {
return listOfAllPossibleProducts[index];
}
}
}
What's currently happening:
My loop is getting the selected id as expected i.e. currentItem, but _.contains(...)
always returns false.
Question:
What is the best way to find the objects in
listOfAllPossibleProducts that have ProductIds that match my
ProductIds in the listOfSelectedProductIds
How about using _.filter:
var result = _.filter(listOfAllPossibleProducts, function (el) {
return _.contains(listOfSelectedProductIds, el.id);
});
Or the non-underscore method:
var result = listOfAllPossibleProducts.filter(function (el) {
return listOfSelectedProductIds.indexOf(el.id) > -1;
});
DEMO
create another structure productsByProductId once!
var productsByProductId = {};
listOfAllPossibleProducts.forEach(p => {
productsByProductId[p.ProductId()] = p
});
and maybe a helper function
function getProductById(id){
return productsByProductId[id];
}
and use this to map the ids to the nodes
var selectedProducts = listOfSelectedProductIds.map(getProductById)
How can I search in this object/array for the first elements to get the field name?
In this example I need to get second if I am searching for #999999
colors = {
first: ['#cccccc', '#999999'],
second: ['#999999', '#626262'],
third: ['#eeeeee', '#afafaf']
};
I tried something like this:
for(var field in colors) {
if(colors.hasOwnProperty(field)) {
if(colors[field] === '#999999') {
console.log(field); // gives 'second'
var color1 = colors[field][0],
color2 = colors[field][1];
}
}
}
Maybe this could get more simplified.
Try using Object.keys() , Array.prototype.filter() ; return property name of object where "#999999" is at index 0 of array
var colors = {
first: ['#cccccc', '#999999'],
second: ['#999999', '#626262'],
third: ['#eeeeee', '#afafaf']
};
var n = "#999999";
var res = Object.keys(colors).filter(function(key, index) {
return colors[key][0] === n
});
console.log(res[0])
colors[field] is the entire Array. You forgot to test against the Array element. Your loop should look more like:
for(var field in colors){
if(colors[field][0] === '#999999'){
console.log(field); // gives 'second'
}
}
If you want to find all the key names with that search parameter in that array position, use an array to capture them. Here's a generic function to solve that just in case you have more than one array with that param in that position.
function find(obj, param, pos) {
var out = [];
for (var p in obj) {
if (obj[p][pos] === param) out.push(p);
}
return out;
}
find(colors, '#999999', 0); // ['second']
find(colors, '#999999', 1); // ['first']
DEMO
I have a Telerik Kendo Grid with a toolbar template for create personalized filters.
I have 2 dropdownlist in my toolbar and the value selection must work in "And" with all filters (including the default filter of the grid).
When i want remove a filter i use this function:
CODE
<script type="text/javascript">
function removeFilter(filter, searchFor) {
if (filter == null)
return [];
for (var x = 0; x < filter.length; x++) {
if (filter[x].filters != null && filter[x].filters.length >= 0) {
if (filter[x].filters.length == 0) {
filter.splice(x, 1);
return removeFilter(filter, searchFor);
}
filter[x].filters = removeFilter(filter[x].filters, searchFor);
}
else {
if (filter[x].field == searchFor) {
filter.splice(x, 1);
return removeFilter(filter, searchFor);
}
}
}
return filter;
}
</script>
My problem is that my function removeFilter remove all the filters in my gridview when instead I would remove only the specific field.
I reproduce an Example in jsfiddle.
QUESTION
What's the correct method for delete only a specific field from the filters of the grid?
REFERENCES
GRID / Toolbar template
remove filter by name of the filed
function removefilter(filterField)
{
//grid id
var gridData = $("#your grid id").data("kendoGrid");
// get currently applied filters from the Grid.
var currFilterObj = gridData.dataSource.filter();
// get current set of filters, which is supposed to be array.
// if the oject we obtained above is null/undefined, set this to an empty array
var currentFilters = currFilterObj ? currFilterObj.filters : [];
// iterate over current filters array. if a filter for "filterField" is already
// remove filter by filed name
if (currentFilters && currentFilters.length > 0) {
for (var i = 0; i < currentFilters.length; i++) {
// for(var j=0; j<)
if (currentFilters[i].field == filterField) {
currentFilters.splice(i, 1);
break;
}
}
}
gridData.dataSource.filter({
logic: "and",
filters: currentFilters
});
}
add filter
function applyFilter(filterField, filterValue) {
// your grid id
var gridData = $("#grid id").data("kendoGrid");
// get currently applied filters from the Grid.
var currFilterObj = gridData.dataSource.filter();
// get current set of filters, which is supposed to be array.
// if the oject we obtained above is null/undefined, set this to an empty array
var currentFilters = currFilterObj ? currFilterObj.filters : [];
// iterate over current filters array. if a filter for "filterField" is already
// defined, remove it from the array
// once an entry is removed, we stop looking at the rest of the array.
if (currentFilters && currentFilters.length > 0) {
for (var i = 0; i < currentFilters.length; i++) {
if (currentFilters[i].field == filterField) {
currentFilters.splice(i, 1);
break;
}
}
}
// if "filterValue" is "0", meaning "-- select --" option is selected, we don't
// do any further processing. That will be equivalent of removing the filter.
// if a filterValue is selected, we add a new object to the currentFilters array.
if (filterValue != "0") {
currentFilters.push({
field: filterField,
operator: "eq",
value: filterValue
});
}
debugger;
// finally, the currentFilters array is applied back to the Grid, using "and" logic.
gridData.dataSource.filter({
logic: "and",
filters: currentFilters
});
}
based on this enter link description here
Your mistake is in myFilterChange function. You add filter on change but never remove the previous one. In the result of this you have condition like idcat == 1 && idcat == 2 after second change of this combo box.
You should clean filter before add another for the same column fiddle:
if (statoFilterValue) {
removeFilter(currFilters.filters, "idstate");
currFilters.filters.push({ field: "idstate", operator: "eq", value: parseInt(statoFilterValue) });
} else {
removeFilter(currFilters.filters, "idstate");
}
Also in removeFilter function you shouldn't use recursion in combination with splice. It is enough to asigne the result of splice
if (filter[x].filters.length == 0) {
console.log('empty');
filter = filter.splice(x, 1);
}