How to use IndexOf in JQuery - javascript

if($('#this').val().indexOf('4289')){
Do something
else
Do something.
This works only with that 4289,
When I try to add other numbers to be indexed next to it using 'or', it doesn't work. How should I put other number. E.g
IndexOf('4289||78843')
I want this to check this numbers and if the number in the input field is not one of this, to echo error.
Here's more which happens to die when one revisits the field.
$('#Zip').blur(function(){
if (($(this).val().indexOf('0860') > -1)||($(this).val().indexOf('0850') > -1)){
$('#Status_Zip').html("No way.")
$(this).alterClass('*_*', 'Success')
return false;
}else{$('#Status_Code').hide()
$(this).alterClass('*_*', 'Error')
$(this).css('border-color', '#F00').css('background-color', '#FFC').effect("pulsate",{times:4},2)
return true;
}
})

That's because it would be looking for the string '4289||78843', which doesn't exist in the target I'm assuming. Logical operators can't just be tossed in anywhere, only where there are actual values to logically operate on. Something like this:
if(($('#this').val().indexOf('4289') > -1) ||
($('#this').val().indexOf('78843') > -1))
The return value of the indexOf() function is the numeric index of that value in the target value, or -1 if it's not found. So for each value that you're looking for, you'd want to check if it's index is > -1 (which means it's found in the string). Take that whole condition and || it with another condition, and that's a logical operation.
Edit: Regarding your comment, if you want to abstract this into something a little cleaner and more generic you might extract it into its own function which iterates over a collection of strings and returns true if any of them are in the target string. Maybe something like this:
function isAnyValueIn(target, values) {
for (var i = 0; i < values.length; i++) {
if (target.indexOf(values[i]) > -1) {
return true;
}
}
return false;
}
There may even be a more elegant way to do that with .forEach() on the array, but this at least demonstrates the idea. Then elsewhere in the code you'd build the array of values and call the function:
var values = ['4289', '78843'];
var target = $('#this').val();
if (isAnyValueIn(target, values)) {
// At least one value is in the target string
}

Related

When I turn document.cookie into an array, and then use conditional statement with indexof, it works only for the first value. Why?

It's hard to even describe the question. I can't reproduce a snippet, obviously because it requires using cookies, but I will try to reproduce it with a normal array, and show you how it should work, then I'll show you screenshots of my code, and the outcome it produces when used on real cookies.
function cookiename(name) {
//var test5 = document.cookie.split(";");
var test5 = ["user=Jim Jordan", "color=blue", "cat=bella", "username=NikoaTesla"];
var username2 = name;
var output = "";
if(test5[0].indexOf("user") == 0) {
output = test5[0].substring(username2.length, test5[0].length);
} else alert("IT DOES NOT WORK");
alert(output);
}
cookiename("user");
This is pretty much what my code looks like, except that, instead of array, test5 is assigned to document.cookie.split(";"), and it contains two more cookies.
Now, the way it works is, you create a conditional statement with the array value, in this case, test5[0], which contains the value "user=Jim Jordan", and say, if the indexof("user") string is in position 0 inside the test5[0] string, which contains the value user=Jim Jordan, then execute the condition, if not, alert that it doesn't work.
Now, as you saw, it works great in the above example. It works as expected with any of the other array values. test5[1], test5[2] etc. will work the same way, of course in the above example they won't match the condition, but if you change the indexof string, it works.
Now, the issue I have is that, the test5 variable stores the document.cookie.split(";") array, and only the first array value works, while the others don't, even though the condition should be matching. However, the other values do work but only if the indexof string is intentionally wrong, and doesn't exist inside the array value, and the condition is of course -1. If the indexof string actually exists, both 0 and -1 conditions don't match. Very strange.
Here's a screenshot of my code, and subsequent result:
First array value
So, as you can see, the first value works as expected.
But then, when I try with another array value, it doesn't work. The third array value is called username=Sam Jones. This is what happens when I change indexof("user") with indexof("username").
Third array value
As you can see, the prior alert that I inserted displays that test5[2] contains the value of username=Sam Jones, but then when use it as a condition, the indexof("username") does not match it. It should be 0, but it's not. Even when I try -1, instead of 0, which matches strings that do not exist, it still produces the exact same outcome! Why!?
Now, watch what happens when I add a string in indexof that does not exist. Instead of the string username, I will add something random, and use -1 as a condition.
Different indexof string on Third array value
As you see, now the random indexof string matches the -1, because it doesn't exist. But why when the indexof string actually does exist, neither 0 nor -1 match the condition?
Why only the first array value work?
Does anyone have any idea what is happening here?
Your approach is flawed since you are expecting that the cookie will always be in the same order. You are also checking for the start of a string equals. When you have user, it will also match username. You are not accounting for the = and you are not removing the encoding.
So to do it with your approach with indexOf and substring, you would need to loop over and check that it has a match
function getCookie(key) {
// var myCookies = document.cookie.split(/;\s?/g);
var myCookies = ["user=Jim%20Jordan", "color=blue", "cat=bella", "username=NikoaTesla"];
for (var i = 0; i < myCookies.length; i++) {
var current = myCookies[i];
if (current.indexOf(key + "=") === 0) {
return decodeURIComponent(current.substr(key.length+1));
}
}
}
console.log('user', getCookie('user'));
console.log('username', getCookie('username'));
console.log('funky', getCookie('funky'));
Most approaches would use a regular expression.
function getCookie(key) {
// var myCookies = document.cookie;
var myCookies = "user=Jim%20Jordan;color=blue;cat=bella;username=NikoaTesla";
var cookieValue = myCookies.match(`(?:(?:^|.*; *)${key} *= *([^;]*).*$)|^.*$`)[1]
return cookieValue ? decodeURIComponent(cookieValue) : null;
}
console.log('user', getCookie('user'));
console.log('username', getCookie('username'));
console.log('funky', getCookie('funky'));
If I have to read multiple values I would map it to an object
function getCookieValues() {
// var myCookies = document.cookie.split(/;\s?/g);
var myCookies = ["user=Jim%20Jordan", "color=blue", "cat=bella", "username=NikoaTesla"];
return myCookies.reduce(function (obj, item) {
var parts = item.split("=");
obj[parts[0]] = decodeURIComponent(parts[1]);
return obj;
}, {});
}
var myCookies = getCookieValues();
console.log('user', myCookies['user']);
console.log('username', myCookies['username']);
console.log('funky', myCookies['funky']);
What you want is to find cookies starting with name, correct?
Firstly, you are probably aware, but it is good to note that if your cookies come this way: cookies = "user=Jim Jordan; color=blue; cat=bella; username=NikoaTesla";, you have to split for "; " instead of just ";".
Once your splits are correct, already without any leading spaces, you only need:
test5.filter(c=>c.trim().startsWith("user"));
I believe startsWith is cleaner than using indexOf.
Another solution, without split:
For the "; " case:
const cookiestr='; '+cookies+';';
while (true) { i=cookiestr.indexOf('; user',i+1); if (i<0) break; console.log(cookiestr.substring(i+2,cookiestr.indexOf(';',i+1))); }
For the ";" case:
const cookiestr=';'+cookies+';';
while (true) { i=cookiestr.indexOf(';user',i+1); if (i<0) break; console.log(cookiestr.substring(i+1,cookiestr.indexOf(';',i+1))); }
In your conditional, test5[2] = “cat=bella”, not “username=NikolaTesla”. That’s at index 3. Could try that?
Also check for white spaces being being added to the front of end of each string like someone mentioned already.

How to detect duplicate characters in an Array, and create an argument accordingly?

Good evening, I attempting to detect duplicate characters in a string. More specifically, I am trying to find up to two different duplicates within an Array. If there is one duplicate, add a sub-string, and if there is another duplicate, add a different sub-string. Is there any way to do this?
Here is some example code I have so far:
var CodeFieldArray = ["Z80.0", "Z80.1", "Z80.0", "Z70.4"];
/* We have an array here used to create the final string at the end of the
code. It is a dummy array with similar variables in my actual code. For
reference sake, there may be only one object in the array, or 7 total,
depending on the user's input, which is where the duplicate detection should
come in, in case the user enters in multiples of the same code. */
var i, Index;
for (i = 0, L = 0; i < CodeFieldArray.length; i++) {
Index = CodeFieldArray[i].indexOf(CodeFieldArray[i]);
if(Index > -1) L += 1;
Extra0 = CodeFieldArray.indexOf("Z80.8");
Extra1 = CodeFieldArray.indexOf("Z80.9");
if(L >= 2 && Extra0 == -1) CodeFieldArray.push("Z80.8");
Extra0 = CodeFieldArray.indexOf("Z80.8");
if(L >= 4 && Extra0 != -1 && Extra1 == -1) CodeFieldArray.push("Z80.9");
console.println(Extra0);
}
/*^ we attempted to create arguments where if there are duplicates
'detected', it will push, "Z80.8" or, "Z80.9" to the end of the Array. They
get added, but only when there are enough objects in the Array... it is not
actually detecting for duplicates within the Array itself^*/
function UniqueCode(value, index, self) {
return self.indexOf(value) === index;
}
CodeFieldArray = CodeFieldArray.filter(UniqueCode);
FamilyCodes.value = CodeFieldArray.join(", ");
/* this is where we turn the Array into a string, separated by commas. The expected output would be "Z80.0, Z80.1, Z70.4, Z80.8"*/
I have it to where it will add "Z80.8" or "z80.9" if they are not present, but they are being added, only if there are enough objects in the Array. My for-loop isn't detecting specifically the duplicates themselves. If there was a way to detect specifically the duplicates, and create an argument based off of that, then we would be doing grand. The expected output would be "Z80.0, Z80.1, Z70.4, Z80.8"
You can use Set and forEach and includes
var CodeFieldArray = ["Z80.0", "Z80.1", "Z80.0", "Z70.4"];
let unique = [...new Set(CodeFieldArray)];
let match = ['Z80.8','Z80.9'];
let numOfDup = CodeFieldArray.length - unique.length;
if(numOfDup){
match.forEach(e=>{
if(!unique.includes(e) && numOfDup){
unique.push(e);
numOfDup--;
}
})
}
console.log(unique.join(','))
So the idea is
Use Set to get unique values.
Now see the difference between length of original array and Set to get number of duplicates.
Now will loop through match array and each time we push item from match array into unique we reduce numOfDup by so ( to handle case where we have only one duplicate or no duplicate ).
In the end join by ,
You could do something like this:
var uniqueArray = function(arrArg) {
return arrArg.filter(function(elem, pos,arr) {
return arr.indexOf(elem) == pos;
});
};
uniqueArray ( CodeFieldArray )

What is wrong with my topology sort

var input = ["KittenService: ", "Leetmeme: Cyberportal", "Cyberportal: Ice", "CamelCaser: KittenService", "Fraudstream: Leetmeme", "Ice: "];
var output = [];
function valid(input) {
for (var i = 0; i < input.length; i++) {
var array = input[i].trim().split(':');
var packageName = array[0].trim();
var dependencyName = array[1].trim();
if (array.length > 1 && dependencyName === '') {
if (output.indexOf(packageName) === -1) {
output.push(packageName);
} else {
return;
}
} else if (array.length > 1 && dependencyName !== '') {
if (output.indexOf(dependencyName) === -1) {
output.push(dependencyName);
if (output.indexOf(dependencyName) > -1) {
if (output.indexOf(packageName) > -1) {
continue;
} else {
output.push(packageName);
}
}
} else if (output.indexOf(dependencyName) > -1) {
output.push(packageName);
}
}
}
return output.join(', ');
}
valid(input);
console.log(output);
I am trying to figure out a way to get the following output:
"KittenService, Ice, Cyberportal, Leetmeme, CamelCaser, Fraudstream"
Right now it logs:
'KittenService, Cyberportal, Leetmeme, Ice, CamelCaser, Fraudstream'
I heard topology sort can fix this, but I am not sure how to implement tsort. How can I do this, or there is other method I can use to fix this? I want to do this without additional library.
Some issues:
The second push in your code is not verifying whether the item that is pushed has some dependencies. For example, the dependency Cyberportal is pushed, but you did not check whether there is maybe a pair where Cyberportal itself has a dependency: which there is... In general, this might then also repeat for the dependency you may find: that also can have another dependency. So you need an iterative or recursive solution here.
The return after the first else is wrong. In some cases this will make your output incomplete. Try your code with the same input, but then "CamelCaser: KittenService" moved to the start of the input array. You'll only get two elements in your output because of this bug.
It is useless to check just after that push whether the pushed element is in the array. You don't need that first if (output.indexOf(dependencyName) > -1): it will always be true.
The other occurrence of if (output.indexOf(dependencyName) > -1) is also useless, as it also will always be true.
It is useless to check for array.length > 1 when you have just applied a method (trim()) to the second element.
You should not let a function put its result in a global variable. Instead create output as a variable local to the function, and return that variable (not a .join() result).
Even with corrections, the algorithm does not have a linear time complexity, since you have indexOf (which is O(n)) within a loop that is also O(n), resulting in a O(n²) time complexity. Yet this can be done in linear time.
Solution
I assume that a certain value is only dependent on at most one other element -- not counting indirect dependencies via that single dependency --, as your notation (with the colon) seems to imply that.
My suggestion is to make use of hash tables, using Set and Map, which provide constant access to their elements. Secondly, with recursion you can make sure to output an element's dependencies first before outputting the element itself.
Here is the ES6 code:
function valid(input) {
let result = new Set(),
pairs = new Map(input.map(s => s.split(': '))),
loop = (_, key) => { // Recursive function to add key with dependencies
if (pairs.get(key)) { // Has dependency
loop(_, pairs.get(key)); // Recurse to add dependencies first
pairs.set(key, null); // Clear dependency
}
// After dependencies were added, now add this key
result.add(key); // Duplicates are ignored
};
pairs.forEach(loop); // Call loop for every element
return [...result]; // Convert Set to Array: order is kept
}
// Sample run:
var input = ["KittenService: ", "Leetmeme: Cyberportal", "Cyberportal: Ice",
"CamelCaser: KittenService", "Fraudstream: Leetmeme", "Ice: "];
var result = valid(input);
console.log(result);
If you do not have ES6 support, you can use plain objects instead of Set and Map. And use normal functions instead of arrow notation.

Javascript string index

I am currently working on some javascript on a website that helps companies see how their campaigns are doing on one collective screen. I am using an if statement to help separate some of the information but the when I go to check the code it says
String index out of range -1
Here is the sample code:
var place = {Media Buy Name};
if(place.indexof("Prospecting")){
return "Prospecting";
}
else if(place.indexof("AudienceTargeting")){
return "AudienceTargeting";
}
else if(place.indexof("Retargeting")){
return "Retargeting";
}
else{
return "Other";
}
1) Javascript is case-sensitive. So indexof is not the same as indexOf.
2) Your place variable is an object literal, so it has no methods except Object's ones unless you define a method manually yourself. Another option is making your variable an instance of Array or String which have indexOf method (1, 2).
So you have to either make your place variable an instance of Array/String or define indexOf method manually within place object. Then your code will work.
For if or else if condition indexOf function return int value so you have to compare it with.
If string found then return its index else return -1.
Check the following link:
http://www.w3schools.com/jsref/jsref_indexof.asp
var place = 'Prospecting'; // Can by dynamic
if(place.indexOf('Prospecting') > -1){
return 'Prospecting';
}
else if(place.indexOf('AudienceTargeting') > -1){
return 'AudienceTargeting';
}
else if(place.indexOf('Retargeting') > -1){
return 'Retargeting';
}
else{
return 'Other';
}

"If" consolidation/avoiding nesting

I'm really trying to avoid nesting in this code snippet...
deal_trade_in_model_1 = document.getElementById('deal_trade_in_model_1').value;
deal_trade_in_amount_1 = document.getElementById('deal_trade_in_amount_1').value;
if (typeof deal_trade_in_model_1 !== 'undefined' && deal_trade_in_model_1 !== null) {
console.log(deal_trade_in_amount_1);
console.log(deal_trade_in_model_1);
if (deal_trade_in_model_1 !== null || deal_trade_in_model_1 !== "") {
if (deal_trade_in_amount_1 == null || deal_trade_in_amount_1 == "") {
console.log('entered into function');
document.getElementById("deal_trade_in_model_1").value = "";
document.getElementById("deal_trade_in_amount_1").value = "";
}
}
}
Basically, what this function does is take the value of two fields... things to know about them and what I want to do to them:
1) They're NOT required
2) If one of them is filled out, the other must be
3) If ONLY one of them is filled out, the user clicks submit, and this part of the function is called upon, I want to delete the value of both of them.
I've tried doing a compound of
&& (and)
and
|| (or)
buttttt it odiously it didn't work.
Primary question: What's the best way to get rid of the nesting (I planned on doing this twice and just swapping the code) that will be the most efficient? This, I want, to be done preferably in the smallest amount of IF statements possible.
Please note: If you change the code a lot, I might not know what you're talking about.. please be prepared to teach me or help me learn!
It sounds like you only want to do something if either of the fields are empty, but not both. Assuming both of the elements are text fields, .value will always return a string. Converting a string to boolean results in false if the string is empty, otherwise true.
So
Boolean(deal_trade_in_model_1) === Boolean(deal_trade_in_amount_1)
will be true if either both fields have a value (both will convert to true) or both fields are empty (both convert to false).
Thus your code can be reduced to
var model_1 = document.getElementById('deal_trade_in_model_1');
var amount_1 = document.getElementById('deal_trade_in_amount_1');
if (Boolean(model_1.value) !== Boolean(amount_1.value)) {
model_1.value = "";
amount_1.value = "";
}

Categories