Underscorejs Contains not acting like indexOf - javascript

I hope someone can explain this to me, in the undescorejs docs, it says:
Returns true if the value is present in the list. Uses indexOf internally, if list is an Array.
I want to see if the user is on the members page by checking if the path contains member. At the moment the path can be '/members/' or '/member/someid`.
So what I have at the moment is
_.contains(['/member'],path);
Which returns false in both cases, but if I check indexOf
path.indexOf('/member');
It returns 0 in both cases.
Why does _.contains seem to act differently than indexOf, and how can I fix it?
UPDATE:
I'm planning to test more pages than just member, that's why I'm using an array in contains()

contains searches a list for elements. If the list is ['a','b','c'] and you search for an element 'a' then you're going to succeed, and if you have a list ['abc','bcd','def'] and you search for an element 'a' you're going to fail, because that's not in the list. We can trivially write code to demonstrate this:
var list = [....];
var find = ...;
list.forEach(function(element) {
console.log("Is "+find+" the same as ["+element+"]? ", element==find);
});
In your example, is 'member' the same as '/member'? It very clearly isn't, they're different strings, and so contains() will report the right thing: your string is not contained in the list you're checking.

Related

Deleting an element from Array (To-Do list app)

I'm creating a To-Do list app, pretty basic and I copied the idea from Youtube (still learning JS). So, each time you add a new To-Do it's stored (just the text you typed and whether it's done or not) in an array and the HTML element is added, everything's good until here.
The problem begins when I try to delete that element from the array. Each item (To-do) has an ID which is basically the index where it's stored in the array, so I coded array.splice(item.id, 1) and It works great if you delete the items patiently one by one, but if you click the delete button faster the items deleted in the array doesn't match, it's like the index passed messes up. I was wondering if I could make like a wait until the current delete() function ends or something like that. Btw the list container has an eventListener and if the delete button of any item was clicked it runs the delete() function passing the item by e.target.parentElement (which is the item container).
I want the array for a localeStorage. Thanks!
First time posting and English isn't my first language, sorry for any mistake.
Great question. So .splice() is indeed the Array method you want to call, but it doesn't quite use the syntax you're expecting.
First of all, I'm going to point you to the MDN docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
MDN is managed by Mozilla, and is an authoritative source on most things javascript-in-the-browser. If you're just getting started with javascript, that resource will be invaluable. The MDN documentation is some of the best written technical documentation out there, and is largely written so that people with minimal experience in the language can understand them.
That being said, let's go over what Array.splice is actually doing.
So you have an array of todos:
const todos = [] // Array of to-dos
You want to delete one of the the todos, and you have access to the id. I'm going to assume your Todos have a shape similar to this:
const todo = {
id: 1 // number
name: 'my todo' // string
description: 'my todo description' // string
}
In order to delete an element from this array, given the id of the item you're deleting, you would actually need to do the following:
1) Find the location in the array of the todo that has the id you are looking for.
2) Splice that element out of the array using the index you just found.
Let's see how to do that:
function removeItemFromTodos(itemId, todos) {
// find the index of the todo with the id you are looking for
const indexOfTodoToDelete = todos.findIndex((todoInArray) => todoInArray.id === itemId));
// remove that todo:
todos.splice(indexOfTodoToDelete, 1) // delete the todo
}
Okay, so let's unpack that:
First, the findIndex method loops over the array. It will start at index 0, and work up until it reaches the end of the array. If the item it is currently looking at has an id that matches the id we are looking for, then the function will immediately return the index of that todo's location in the array, and stop searching in the array.
Once you have the index, you can delete the item. The splice function takes in the location that you want to start cutting elements as the first argument, and the number of elements you want to cut as the second argument. The splice method returns the elements that were deleted. So it is actually mutating the array in place, and not making a copy of it in memory to perform its operation.
Let me know if this solution doesn't work for you or if it isn't clear!

Target search results number in variable

I'm trying to target the number of search results on our website for each search term so that I can see how many results each one pulls in.
I'm working off of this article, but I can't get the javascript function correct to pull out the number (which could be as high as 2000) and put it into a variable.
<div class="search-results-text"><strong>732 results</strong> found for ‘<strong>search term</strong>’</div>
Hoping someone can help me out with the javascript function that would grab that number before "results". Thanks!
You would probably get away with a custom Javascript variable like this:
function() {
return document.querySelector('.search-results-text strong').innerText.split(" ")[0];
}
The querySelector with the CSS selector gets the Element, innerText is the text without the markup, the split splits the string up by whitespace, which gives you an array, and the first element of that array is your number (array are index starting with zero, so [0] refers to the first element).
This is not particularly elegant (for one you probably want to add some sort of error handling), and you could actually replace document.querySelector('.search-results-text strong').innerText with a DOM type variable in GTM (which by default returns the text of the element).
I don't think you can get the number with CSS selectors alone.

linqjs intersect comparer issue

I am using linqjs and I have one array full of ids to include in a list, and an array full of complex objects which have a property userId.
Problem is when I do an intersection it never seems to return anything, however there is very little information around the compareSelector.
So here is an example of what I am doing:
enumerableOfUsers.intersect(listOfIdsToInclude, "$.userId");
So in the above example enumerableOfUsers would be an existing enumerable created from an array of users (which contain the userId field), the listOfIdsToInclude is an array of id values, like ["12345", "213213", "2124"] etc.
The intersect seems to work but never returns anything and I know the userIds match so am I doing anything wrong here?
The thing is that the compare selector is applied to items of both the first and second sets. The second set is a list of ids already so the compare selector doesn't apply. The projection yields undefined values which will always result in no results found.
You need to apply the selector only to the first set of values. Try this instead:
// using linqjs 2.x syntax
var query = enumerableOfUsers.Select("$.userId").Intersect(listOfIdsToInclude);

How to check if multiple checkboxes with same name present or only one such checkbox present?

How exactly do you check if the checkbox value you are getting is a variable or an array. I have a PHP script which dynamically populates a form with checkboxes based on the number of directories present in a folder. Now as long as there is more than one directory I can use the following code
for (i=0;i<document.getElementById('editarticle').currentcategories.length;i++)
{
if
(document.getElementById('editarticle').currentcategories[i].checked==true)
{
currentcheckedcategories[currentcheckedcategoriescounter] =
document.getElementById('editarticle').currentcategories[i].value;
currentcheckedcategoriescounter++
}
else
{
currentnotcheckedcategories[currentnotcheckedcategoriescounter] =
document.getElementById('editarticle').currentcategories[i].value;
currentnotcheckedcategoriescounter++
}
}
However, if current-categories is not an array, i.e there is only one category, then I get an undefined and the category value is not collected. Is the only way to bypass this problem by checking if currentcategories is an array prior to running the for loop? If so how would I check if the currentcategories is an array. I read on another forum that you could use instance of Array but that doesn't seem to work and another website said that doing so would not be fail safe as it would fail one was using iFrames. Hope someone can shed light on how to check if currentcategories is an array or offer alternative code for my problem. Thanks in advance.
PS. I need the code to be in JavaScript and not JQuery or any other framework.
Partially Solved
Well, so far I have used the following if statement to check if the multiple checkboxes with the same name are present or not.
if(document.getElementById('editarticle').currentcategories.length == undefined)
An undefined means that only one checkbox with that name is available. Otherwise their are multiple currentcategories checkboxes which can be selected. Seems to work in IE 8 Firefox and Chrome. Not convinced it is the best method. Perhaps if someone sees a flaw in this implementation or a better solution please do let me know.
I tried Edorkas code but the that code returns true for array based on currentcategories values. Hence, if I have three checkboxes named currentcategories and only one is selected then the code would return false for array. Of course this is probably my fault as I worded the title of this question as "How to check if checkbox value is array" perhaps a better title would be "How to check if multiple checkboxes with same name present." I have changed that to better reflect my question.
If the object has the attribute length defined it should be an array. Be careful about the comparison because if (result.length) will be false when the array is empty. However this function will be much more useful, found in this answer Check if object is array?
window.isArray = function(candidate){
if (candidate == null)
return false;
return ( Object.prototype.toString.call(candidate) === '[object Array]' )
}

LINQ-For-Javascript Nested Arrays

The Linq-For-Javascript library contains functions that convert between "jQuery objects" and "Enumerable objects": toEnumerable() and TojQuery(). Consider the difference between these two lines:
$('tr'); // returns array of tr
$('tr').toEnumerable().TojQuery(); // returns array of tr[1]
Converting from jQuery to Enumerable and back to jQuery does not give you what you started with. The end result is an array of arrays of elements, with each sub-array having a length of 1. I do need to make use of Enumerable, so this is just a convenient example of my problem.
This means that to get the id of an element, you'd need to do the following:
$('tr')[0].id; // returns "myID"
$('tr').toEnumerable().TojQuery()[0][0].id; // returns "myID"
I'm surprised of this, because even though I've allegedly gone back TojQuery(), the object returned by TojQuery() does not work with typical jQuery calls:
$('tr').find('td').length; // returns 170 (in my case)
$('tr').toEnumerable().TojQuery().find('td').length; // returns 0 (BAD)
I would like it if both lines returned 170, but apparently Linq-For-Javascript doesn't work that way.
So, my questions:
Why is this?
Am I doing it wrong?
If not, any good workarounds? (convert array of 1-element arrays to array of elements?)
Thanks!
JQuery handles operations according to types. In the first line of the code, if finds all HTML TR objects and by the help of this information it can attach necessary functions to the found objects.
$('tr').find('td')
However, it could not understand after you change it to enumarable object since it is no longer seems to be a HTML Object instead it becomes any other type of object. Thus, jquery cannot attach a function to it.
$('tr').toEnumerable()

Categories

Resources