Hi i need to iterate over each title in this code. However, i'm getting some error in console that states cannot use 'in' operator. This code works fine when i pass an id that is coming from database. But i need to pass in a string, then it throws error right after each function is called. I can't figure out why, one thing i can think of is there is possible JSON/string conflic. How do i resolve that. Any help would be appreciated thanks.
function getFilteredBySearch(searchString){
return priv.availablePrintables.filter(function(printableModel) {
var result = false;
var title = printableModel.getTitle();
$.each(title, function(idx, id) {
if (id == searchString) {
result = true;
return false; // break out of the 'each' loop
}
})
return result; // return from the callback
});
}
RESOLVED:
The following worked!
if ((printableModel.getTitle()).indexOf(searchString) > -1){
result = true;
console.log(result);
}
I think you're trying to iterate over the collection, when the filter method already does that for you. You don't need jQuery to loop over a number of items, when you only have one to examine. Try this:
function getFilteredBySearch(searchString){
return priv.availablePrintables.filter(function(printableModel) {
return (searchString == printableModel.getTitle());
});
}
(I'm not that familiar with backbone.js, so I might have the syntax slightly wrong)
This is only made based on assumptions: probably sometimes getTitle method return string and sometimes returns array of strings (because you've pointed out that console logs out ["book"] when you get title). You can check what type of object it returns:
function getFilteredBySearch(searchString){
return priv.availablePrintables.filter(function(printableModel) {
var title = printableModel.getTitle();
if(typeof title == 'string'){
//if it's string
return (title == searchString);
}else{
//if it's array
return (title.indexOf(searchString) != -1);
}
});
}
Related
I'm new to javascript, and scratching my head over this issue:
I used to use the following to grab a bunch of product titles from the page:
CODE 1:
var productTitles = document.querySelectorAll(".product-title");
Then I used the following code to ad a list of these titles to a form's textarea field:
CODE 2:
var MyTextAreaField = document.querySelector("#my-textarea-field");
MyTextAreaField.value = [...productTitles].map(el=>el.textContent).filter(txt=>txt !== 'None').join('\n');
The above worked great, however, I just changed CODE 1 to be a function instead (in order to conditionally return product titles)
The below code is just a rough example of what it looks like:
CODE 3:
var productTitleOne = document.querySelectorAll(".product-title1");
var productTitleTwo = document.querySelectorAll(".product-title2");
var productTitleThree = document.querySelectorAll(".product-title2");
function createProductTitles() {
if (productTypeOne == null) {
return productTitleOne.textContent;
} else if (productTypeTwo == "None") {
return productTitleTwo.textContent;
} else {
return productTitleThree.getAttribute("data-qty") + 'x' + selectionItem.textContent ;
}
}
Problem is, now code 2 no longer works, because it is no longer an Array
So, I tried doing this (adding my function to a variable):
var productTitles = createProductTitles();
But the following still doesn't work, because it's still not really an array
MyTextAreaField.value = [...productTitles].map(el=>el.textContent).filter(txt=>txt !== 'None').join('\n');
So how do I get the result of my function to post to my textarea field?
The problem is the value you're returning on createProductTitles in the Code 1 you're using the array returned by var productTitles = document.querySelectorAll(".product-title"); in the Code 3 you're returning the textContent of that selector, i.e. return productTitleOne.textContent;.
It's important to make a distinction between these two codes because they're sending different data types one is returning an array and the other is returning a string.
So, you need to change your function to return the same the result of the querySelectorAll function
var productTitleOne = document.querySelectorAll(".product-title1");
var productTitleTwo = document.querySelectorAll(".product-title2");
var productTitleThree = document.querySelectorAll(".product-title2");
function createProductTitles() {
if (productTypeOne == null) {
return productTitleOne;
} else if (productTypeTwo == "None") {
return productTitleTwo;
} else {
return productTitleThree
}
}
and then use your function
var productTitles = createProductTitles();
Your function in CODE 3 needs to change.
document.querySelectorAll() returns a NodeList (similar to an array). So it's no good to then try and access the textContent property or call getAttribute() as you do in that function, both of which should instead be called (if desired) on the individual Nodes in the NodeList.
You can modify that function so that the calls you have made take place on the individual Nodes using the spread operator and map function, similarly to how you did in CODE 2:
function createProductTitles() {
if (productTypeOne == null) {
return [ ...productTitleOne].map( productTitles => productTitles.textContent );
} else if (productTypeTwo == "None") {
return [ ...productTitleTwo].map( productTitles => productTitles.textContent );
} else {
return [...productTitleThree].map( productTitles => productTitles.getAttribute("data-qty") + 'x' + selectionItem.textContent );
}
}
This function will return an array of string values that you can do with as you wish, such as:
createProductTitles().filter(txt=>txt !== 'None').join('\n');
I have this piece of code running on the client that filters a list of events:
if (res)
{
eventList.filter(function(event) {
const out = res.find(function(visibility) { return visibility.ID == event.id; }) == undefined;
return out;
});
alert(eventList);
}
displayEvents(eventList);
The problem is that even when out is false the element is not filtered out.
Just for debug I tried to return false in any case and the resulting array still had all the initial elements:
eventList.filter(function(event) {
return out;
});
What am I doing wrong here??
EDIT:
res is an array of JSON objects (containg only ID field) returned by the server, while eventList is a list of Facebook events, passed to this callback function from a Facebook API request
Array.prototype.filter does not change array inplace, it returns new array made of items that satisfies the provided predicate. It should look like this
var result = eventList.filter(function(event) {
return res.find(function(visibility) { return visibility.ID == event.id; }) === undefined;
});
You don't need to declare and assign variable and then return it from function, you can simply return expression
So I researched about Promises and concluded that by using the .then, it will "actually execute" the asynchronous function inside it. Then, I proceed on updating my code to this:
function getCurrentKey(){
return tailorRef.once('value').then(function(data){
data.forEach(function(childData){
if ( (loggedUname == childData.val().tUsername) && (loggedPword == childData.val().tPassword) ){
Ukey = childData.key;
}
});
return Ukey;
});
}
currentKey = getCurrentKey();
console.log("key = " + currentKey);
NOTE: the var currentKey is global
The expected output in the console would be key = "some unique key" but instead, it shows key = [object Promise]. I tried to put .val() after the childData.key to actually get the value and not the object, but it didn't work.
Is there something wrong with my Promise implementation or its structure? or is my conclusion wrong?
Because the first return happens before the resolve part is executed.
If you really want to print your currentKey, do something like this.
function getCurrentKey(){
tailorRef.once('value').then(function(data){
data.forEach(function(childData){
if ( (loggedUname == childData.val().tUsername) && (loggedPword == childData.val().tPassword) ){
currentKey = childData.key;
printCurrentKey(currentKey);
}
});
});
}
printCurrentKey(key){
console.log(key)
}
Note: Do take care of the scope while calling printCurrentKey.
I have written a method called contains which checks a string to see if it has a specified string in inside it (see below for code).
Since this code works for strings, I would like to also have it work on arrays, but I cannot find a way to do that (if I create another method of the same name but with Array instead of String it raises a TypeError).
How would I do this?
Code:
String.prototype.contains = function(subst) {
var string = this;
if (string.indexOf(subst) == -1) {
return false;
} else {
return true;
}
}
Thanks in advance for any help :)
BTW: I am writing this, rather than using the built in indexOf, method just to improve the readability of my code.
EDIT:
Here is the code that is causing the error:
Array.prototype.contains = function(subst) {
var array = this;
if (array.indexOf(subst) == -1) {
return false;
} else {
return true;
}
}
And I am calling it using:
var arr = ['1','2','3','4'];
console.log(arr.contains('1'));
Which raises the error:
Uncaught TypeError: arr.contains is not a function
I am writing a search function at the moment for my Backbone application, the idea is that a user can enter a string and the app will search for and return any matching models where the string appears in any of its attributes. So far I have the following,
view function run on keyup,
this.results = this.collection.search(letters);
This runs the following code located in the collection,
search: function( filterValue ) {
filterValue = filterValue.toLowerCase();
var filterThroughValue = function(data) {
return _.some(_.values(data.toJSON()), function(value) {
console.log(value);
if(value != undefined) {
value = (!isNaN(value) ? value.toString() : value);
return value.toLowerCase().indexOf(filterValue) >= 0;
}
});
};
return App.Collections.filterCollection = this.filter(filterThroughValue);
}
However running this I get the following error,
Uncaught TypeError: undefined is not a function
this error is shown as being the line return value.toLowerCase().indexOf(filterValue) >= 0; and this error gets returned whether or not I use a string I know exists in a model of the collection.
Is there a fix for this, or a better way of searching and returning only models that have models that contain the search string?
Since you just want a string representation of value, you can probably just check if value has a toString method. Note that String also has a toString method, so this will work if value is a String.
return _.some(_.values(data.toJSON()), function(value) {
if(value && value.toString) {
return value.toString().toLowerCase().indexOf(filterValue) >= 0;
}
return false;
}