Syntax problems. Knockout. For filtering - javascript

I'm working with jquery, Json data and knockout. What i did is to get a data, add to binded table and a filter field for name.
The thing is, that filter field works not as i want it to work. Because it matches the whole word. That is the code:
self.filter = ko.observable();
self.tickets = ko.computed(function () {
var filter = self.filter(),
arr = [];
if (filter) {
ko.utils.arrayForEach(self.ticketViewModel(), function (item) {
if (item.Name() == filter || item.Status() == filter) {
arr.push(item);
}
});
} else {
arr = self.ticketViewModel();
}
return arr;
});
So i'm trying to make that it would start filtering from the first letter. And i found several methods, which should work, but i can't get the result because i always get various errors of syntax. Maybe who have used these could help me out. The code for it:
self.filter = ko.observable().toString().toLowerCase();
self.tickets = ko.computed(function () {
var filter = self.filter(),
arr = [];
if (!filter) {
arr = self.ticketViewModel();
} else {
ko.utils.arrayFilter(self.ticketViewModel(), function (item) {
if (ko.utils.stringStartsWith(item.Name().toLowerCase()), filter)
arr.push(item);
})
}
return arr;
});
The last error i got was - Uncaught TypeError: string is not a function on line
var filter = self.filter()
The same error i got a few times, but after fixing that i get another ones when usually i get back to it again... And sorry for my english.
I can post the whole code if needed.

Managed to find an answer myself, finally.
Instead of using ko.util.stringStartsWith(), i'm using a simple Javascript checking. And it works perfectly. Maybe it will be useful for someone.
self.filterName = ko.observable('');
self.filterCompany = ko.observable('');
self.filterStatus = ko.observable('');
self.tickets = ko.computed(function () {
return ko.utils.arrayFilter(self.ticketViewModel(), function (rec) {
return (
(
(self.filterName().length == 0 || (rec.Name().toLowerCase().indexOf(self.filterName().toLowerCase()) > -1)) &&
(self.filterCompany().length == 0 || (rec.CompanyName().toLowerCase().indexOf(self.filterCompany().toLowerCase()) > -1)) &&
(self.filterStatus().length == 0 || (rec.Status().toLowerCase().indexOf(self.filterStatus().toLowerCase()) > -1))
)
)
});
});

Related

JavaScript .startWith() function not working in IE, inside angularjs project

Hi im using Angularjs for my project, There is nationality search drop down. I want to map which is typing on Input and filter it inside nationality JSON object. This part is working fine in other browsers except IE. There is console error "Object doesn't support property or method 'startsWith'". this is my code, Can i know how to add "String.prototype.startsWith" for this issue for my code.
$scope.searchNationality = function (data) {
var output = [];
if (data != "" && data != undefined) {
$scope.ShowNationalityDropDown = true;
for (var i = 0; i < $scope.nationalityList.length; i++) {
if ($scope.nationalityList[i].content.toLowerCase().startsWith(data.toLowerCase())) {
output.push($scope.nationalityList[i]);
}
}
$scope.nationalityListSearchResults = output;
} else {
$scope.ShowNationalityDropDown = false;
$scope.nationalityListSearchResults = [];
}
};
You can try changing from .startsWith to .indexOf since it is compatible with IE for lower versions. If .indexOf returns 0 then the string is in the first position of the string that calls that function, which can be usable when you are in this kind of situation that you can't use .startsWith().
const str = "Hey this is a sample string!"
console.log(str.indexOf("Hey") === 0)
console.log(str.indexOf("sample") === 0)
$scope.searchNationality = function (data) {
var thereIsData = data != "" && data != undefined;
var output = thereIsData
? $scope.nationalityList.filter(function (nationality) {
return nationality.content.toLowerCase().indexOf(data.toLowerCase())) == 0;
})
: [];
$scope.ShowNationalityDropDown = thereIsData;
}

Using Javascript/JQuery to Filter XML results

Ok, I am doing my nut trying to figure this out...
I have a page that pulls up a bunch of XML data and it is working fine.
I then decided to add a search box on this and other pages that will make this page only show the results of my search.
I know that the page is receiving the form data and that it is being correctly stored in variables.
I want to use those variables to then filter the results of my xml file.
What I have currently is;
var x=xmlDoc.getElementsByTagName("ResidentialProperty");
mySearch = location.search.substr(1).split("&")
function getFromSearch() {
var x = 0
mySearch = location.search.substr(1).split("&")
for (x=0;x<=mySearch.length;x++) {
eval("document.forms.myNewForm."+mySearch[x])
}
}
document.write(mySearch);
for (i=0;i<x.length;i++) {
var item = x[i];
document.write("<div class='property'><div class='list_name'>");
if(item !== undefined) {
var itemElements = item.getElementsByTagName("StreetNumber");
if(itemElements.length > 0) {
if(itemElements[0].childNodes.length > 0) {
document.write(x[i].getElementsByTagName("StreetNumber")[0].childNodes[0].nodeValue+' ');
}
}
}
if(item !== undefined) {
var itemElements = item.getElementsByTagName("StreetDirPrefix");
if(itemElements.length > 0) {
if(itemElements[0].childNodes.length > 0) {
document.write(x[i].getElementsByTagName("StreetDirPrefix")[0].childNodes[0].nodeValue+' ');
}
}
}
etc.
This is all working but every time I try to filter it just stops all results returning.
Please help.
Might be worth using a library like jQuery for this problem.
e.g. (taking a stab at the code without any testing)
var xml = $(xmlDoc);
var properties = xml.find('ResidentialProperty');
mySearch = location.search.substr(1).split("&");
var results = properties.filter(function() {
return $(this).val().substr(0, mysearch.length) === mySearch;
});
console.log(results);
Reference
http://www.jquerybyexample.net/2013/02/jquery-parse-json-xml-html.html
https://api.jquery.com/find/
http://api.jquery.com/filter/

Emberjs: Paginating Fixture Data

I'm building a search box that filters through records and looks for any entity that has the specified number in the searchBy category:
MyApp.SearchController = Em.ObjectController.extend({
searchTerm: "",
searchBy: "id",
searchFor: "customer",
results: function(){
if(this.get('searchTerm') !== ""){
var searchObj = {};
searchObj[this.get('searchBy')] = this.get('searchTerm');
var that = this;
return this.store.all(this.get('searchFor'))
.filter(function(entity){
return ('' + entity.get(that.get('searchBy'))).indexOf(that.get('searchTerm')) != -1;
});
} else return [];
}.property('searchTerm', 'searchBy', 'searchFor'),
...
});
However there is a large CPU spike as soon as i hit '1' as it will filter through every record and check each id.
Is there a way to limit the filter so that it only returns the first 10 matches?
There are a few things you can do, first off, throttling/debounce should probably be used here, http://emberjs.com/api/classes/Ember.run.html#method_debounce. Here's an example of debouncing, start typing, it won't start searching until you've stopped typing for at least 500 ms. http://emberjs.jsbin.com/covovaye/2/edit
You don't need to call all, then filter, just call filter and send it a function as the filter. Additionally you can save quite a few calls to get by getting searchBy and searchTerm, then using those variables over and over, instead of calling get over and over.
results: function(){
if(this.get('searchTerm') !== ""){
var searchObj = {},
searchBy = this.get('searchBy'),
searchTerm = this.get('searchTerm');
searchObj[searchBy] = searchTerm;
var that = this;
return this.store.filter(this.get('searchFor'), function(entity){
return ('' + entity.get(searchBy)).indexOf(searchTerm) != -1;
});
} else return [];
}.property('searchTerm', 'searchBy', 'searchFor')
If you really wanted to get the first 10 you could use slice
results: function(){
if(this.get('searchTerm') !== ""){
var searchObj = {},
searchBy = this.get('searchBy'),
searchTerm = this.get('searchTerm');
searchObj[searchBy] = searchTerm;
var that = this;
return this.store.all(this.get('searchFor'))
.toArray()
.slice(0,10)
.filter(function(entity){
return ('' + entity.get(searchBy)).indexOf(searchTerm) != -1;
});
} else return [];
}.property('searchTerm', 'searchBy', 'searchFor')

How do I remove all the extra fields that DOJO datastore adds to my fetched items?

When fetching an item from a DOJO datastore, DOJO adds a great deal of extra fields to it. It also changes the way the data is structure.
I know I could manually rebuild ever item to its initial form (this would require me to make updates to both JS code everytime i change my REST object), but there certainly has to be a better way.
Perhaps a store.detach( item ) or something of the sort?
The dojo.data API is being phased out, partly because of the extra fields. You could consider using the new dojo.store API. The store api does not add the extra fields.
I have written a function that does what you are looking to do. It follows. One thing to note, my function converts child objects to the { _reference: 'id' } notation. You may want different behavior.
Util._detachItem = function(item) {
var fnIncludeProperty = function(key) {
return key !== '_0'
&& key !== '_RI'
&& key !== '_RRM'
&& key !== '_S'
&& key !== '__type'
};
var store = item._S;
var fnCreateItemReference = function(itm) {
if (store.isItem(itm)) {
return { _reference: itm.id[0] };
}
return itm;
};
var fnProcessItem = function(itm) {
var newItm = {};
for(var k in itm) {
if(fnIncludeProperty(k)) {
if (dojo.isArray(itm[k])) {
// TODO this could be a problem with arrays with a single item
if (itm[k].length == 1) {
newItm[k] = fnCreateItemReference(itm[k][0]);
} else {
var valArr = [];
dojo.forEach(itm[k], function(arrItm) {
valArr.push(fnCreateItemReference(arrItm));
});
newItm[k] = valArr;
}
} else {
newItm[k] = fnCreateItemReference(itm[k]);
}
}
}
return newItm;
};
return fnProcessItem(item);
};
NOTE: this function is modified from what I originally wrote and I did not test the above code.

Dynamic arrays in Javascript/JQuery

Why does my array length always come out to 0 even though var email is equal to a string. (I've alerted out var email and the data is there).
var emails = new Array();
//get all the emails
$('.emailBox input').each(function (i)
{
var email = $(this).val();
if(email != '')
{
emails[email] = email;
alert(emails.length);
}
});
Because you're adding a property to the array.
var a = [];
a.foo = 42;
a.length === 0; // true
Instead try
emails.push(email);
This is the same as emails[emails.length] = email
As an aside:
var emails = new Array();
Is bad. You should be using [] instead of new Array() mainly because it's more terse and readable.
if (email != '') {
The above can be replace with if (email) { in case jQuery ever returns undefined or null
To make the entire code more elegant you should use
var emails = $('.emailBox input').map(function() {
return this.value;
}).filter(function (k, v) { return v; }).get();
Or without jQuery
var emails = [].map.call(document.querySelectorAll(".emailBox input"), function (v) {
return v.value;
}).filter(function (v) { return v; });
Although you'll need a QSA shim and a ES5 shim for legacy platform support.
Edit:
If you want the array to be unique then reduce it.
var arr = arr.reduce(function (memo, val, key, arr) {
// if the first index of the value is the index then add it.
// if the first index is different then we already have it.
if (arr.indexOf(val) === key) {
memo.push(val);
}
return memo;
}, []);
You could do all of that using a few jQuery methods.
var emails = $('.emailBox input')
.map(function() { return $(this).val() || null; })
.get();
jsFiddle.
emails[email] = email isn't doing what you want it to do. Try
emails.push(email);

Categories

Resources