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';
}
Related
Im trying to change the class of some elements based on an array.
I have declared a function to return a boolean and say if the string(state/class) is contained in the array.
I have call it isState(st: string) {return (this.ArrayWithClasses.indexOf(st) > 0)}
And then I do
[ngClass]="{'class-I-Want-To-Activate': isState('evaluating-this-state') }"
But it is´t working. You see my mistake? A best solution?
Edit: It is working if I use just a boolean to toggle the class. So I consider if function is what is wrong...
You shouldn't check if indexOf() value is > 0, because, if that string is located on the first place in array, you will get 0.
isState(st: string) {
let temp = this.ArrayWithClasses.indexOf(st);
if(temp != -1)
return true;
else
return false;
}
If searched string is not located in the array , you will get -1 value for that.
Use the below
isState(st: string) {
let temp=this.ArrayWithClasses.indexOf(st)
if(temp)
return true;
else
return false;
}
The function is given an array of 2 elements, 2 string to be exact. If the first element has every single letter in the second element (just one time, no case, no order), then the function returns true, if not false.
hey and hello works. But for example, mutation(["zyxwvutsrqponmlkjihgfedcba", "qrstu"]) is not returning true, somehow. I suspect there is something wrong with my if statement nested inside my for loop. Am I returning false or true multiple times, or some other problem?
function mutation(arr) {
var one=arr[0];
var two=arr[1];
one.toLowerCase();
two.toLowerCase();
var array=two.split("");
for(var i=0;i<array.length;i++){
if(one.indexOf(array[i]) !== -1){
return false;
}else return true;
}
}
mutation(["hello", "hey"]);
EDIT:
New discovery! if I move else return true to right after the end bracket of the for loop, mutation("hello", "neo") would return false, as wanted. But if I did that, then, mutation("hello", "hey") wouldn't return true, whereas before the change, it would.
This:
for(var i=0;i<array.length;i++){
if(one.indexOf(array[i]) !== -1){
return false;
}else return true;
}
is essentially (close enough) the same as this:
if(one.indexOf(array[0]) !== -1){
return false;
}else return true;
That is, you're not actually looping over anything. Because, no matter what, your loop always returns on the first iteration.
Consider the logic of what your function should do. If I understand correctly, you want to return false if the loop ever encounters a letter that isn't found in one. And to return true if the loop never encounters such a match. In that case, the default condition after the loop would be to return true. Something like this:
for(var i=0;i<array.length;i++){
if(one.indexOf(array[i]) === -1){
return false;
}
}
return true;
Basically, if the loop never found a "non-match", then it never returned false. So return true.
Edit: I also changed the comparison in the if, because I think you had it reversed. But I guess I'm not 100% sure on that, since the intent of the method is a little unclear. (The logic therein is a bit confusing, and the name of the method certainly doesn't help.) But hopefully you at least get the idea and can test/validate accordingly for your needs.
First, you should only return false if you find any character in one that wasn't in two, but you can only return true at the end of the loop, because then you know all characters match. It can't be in the else block.
Second, Shouldn't it be the other way around based on your description? You should iterate the characters of one and see if they are in two instead. Then it would fit.
function mutation(arr) {
var one=arr[0].toLowerCase();
var two=arr[1].toLowerCase();
var oneArr=one.split("");
var twoArr=two.split("");
console.log("Do all of '" + one + "' characters occur in '" + two + "'?");
for(var i=0;i<oneArr.length;i++){
console.log("Looking for " + oneArr[i]);
// If any characters in two didn't occur in one, it fails
var twoIndex = twoArr.indexOf(oneArr[i]);
if(twoIndex === -1) {
console.log("Can't find " + oneArr[i]);
return false;
} else {
console.log("Found at index " + twoIndex + " in '" + two + "'");
}
}
return true;
}
console.log(mutation(["hey", "hello"]));
console.log(mutation(["qrstu", "zyxwvutsrqponmlkjihgfedcba"]));
The main issue is that you're using an else block to return true inside the loop, so your loop is only checking one element then either returning true or false based on whether or not that element is in the first string. Put the return true statement after the for loop.
The second issue is that when you're checking for existence, you're returning false if it does exist. Use one.indexOf(array[i]) === -1 instead.
The final issue is that you're splitting a string to iterate it, but strings don't need to be split to be iterated using a for loop.
The rest of the changes just use less lines of code to do the same thing.
function mutation(arr) {
arr = arr.map(e => e.toLowerCase());
for(let i = arr[1].length - 1; i > -1; --i)
if(arr[0].indexOf(arr[1][i]) === -1) return false;
return true;
}
console.log(mutation(["hello", "hey"]));
console.log(mutation(["hello", "hel"]));
console.log(mutation(["zyxwvutsrqponmlkjihgfedcba", "qrstu"]));
function addNumifnotThere(numer){
var numCent = [];
numCent.forEach(function(){
if(numer in numCent)
console.log("you logged that");
else
numCent.push(numer);
});
return numCent;
}
This is my current code, what its attempting to do is read an array and if there is already an element exits the loop and says "you already logged that", obviously if it cannot find a similar element then it pushes it to the array.
I want this to work dynamically so we cannot know the size of the array beforehand, so the first element passed as an argument should be put into the array, (addNum(1) should have the array print out [1], calling addNum(1) again should print "you already logged that")
However there are two problems with this
1) Trying to push to a new array without any entries means everything is undefined and therefore trying to traverse the array just causes the program to print [].
2) Adding some random elements to the array just to make it work, in this case numCent=[1,2,3] has other issues, mainly that adding a number above 3 causes the code to print incorrect information. In this case addNum(5) should print [1,2,3,5] but instead prints [1,2,3,5,5,5]
I know this has to be a simple mistake but I've been dragging myself too long to not ask for help.
EDIT: Thanks to the many outstanding answers here I have now leanred about the indexOf method, thank you guys so much.
For every non-match you are pushing the number. Use something like this
var numCent = [];
function addNumifnotThere(numer)
{
var index = numCent.indexOf(number);
if(index >=0)
{
console.log("you logged that");
}
else
{
numCent.push(number);
}
return numCent;
}
Use Array.prototype.indexOf
var numCent = [];
function addNum(numer){
if (numCent.indexOf(numer) > -1)
{
console.log("Number already in array");
}
else
{
numCent.push(numer);
}
}
//DEMO CODE, not part of solution
document.querySelector("button").addEventListener("click", function(){
if (document.querySelector("input").value.length > 0)
{
addNum(document.querySelector("input").value);
document.querySelector("div").innerHTML = numCent.join(", ");
}
}, false);
Output
<div id="output"></div>
<input />
<button>Add number</button>
indexOf tests if an element is inside the array and returns its index. If not found it will return -1. You can test for this. You can try it for your self in this snippet. It will only allow you to add a number (or any string, in this example) once.
I also was confused by the newCent array declaration inside the function. I think, based upon the content of your question, you meant this.
If you want the array held in the instance, you can do it like this.
function AddIf(arr){
if( arr || !this.arr ) {
this.arr = arr || [];
}
return function(number) {
if( this.arr.indexOf(number) >= 0 ) {
console.log("Already Present!");
} else {
this.arr.push(number);
}
return this.arr;
}.bind(this);
}
// Usage would be like this:
// var addIf = new AddIf([1, 2, 3]);
// addIf(10); // returns [1, 2, 3, 10]
// addIf(10); // logs "Already Present!", doesn't add 10 to array
This basically returns a function, with this bound to the function being called. If you pass in an initial array, it will use that array to compare to when adding it to the array.
You can catch the return function and call it as you would want to. If you don't call new when invoking however, it will share the same array instance (and have a funky way of being called, AddIf()(10)).
I used fn.bind() to ensure the function gets called in the correct context every time, if you were wondering why I called it like that.
Do do this cleanly, I'd consider prototyping the global Array object and adding a method to push values but only if they're unique to the array. Something like this:
Array.prototype.pushUnique = function (item) {
if (this.indexOf(item) != -1) {
console.log("Item with value of " + item + " already exists in the array."
}
else {
this.push(item);
}
}
If you're not comfortable prototypeing global types like Array, you can build the same thing in a procedural pattern:
function arrayPushUnique (arr, item) {
if (arr.indexOf(item) != -1) {
console.log("Item with value of " + item + " already exists in the array."
}
else {
arr.push(item);
}
}
Then to use it, simply create a new empty array and start pushing things to it.
var numCent = [];
// The Array.prototype method
numCent.pushUnique(number);
// The procedural method
arrayPushUnique(numCent, number);
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
}
what is the best way of finding out if a text input includes a specific text with JQuery?
For example, how can I find out and return a Boolean result if $('#poo').val() includes airport?
EDIT
Here is the solution to my problem thanks to #Niklas;
var IsbtFortxtPropertyHotelNameOn = false;
$('#<%: txtPropertyHotelName.ClientID %>').keyup(function() {
if (/airport/i.test(this.value) && !IsbtFortxtPropertyHotelNameOn) {
$('#<%: txtPropertyHotelName.ClientID %>').btOn();
IsbtFortxtPropertyHotelNameOn = true;
} else if(IsbtFortxtPropertyHotelNameOn && !/airport/i.test(this.value)) {
$('#<%: txtPropertyHotelName.ClientID %>').btOff();
IsbtFortxtPropertyHotelNameOn = false;
}
});
If you want to have control over the case-sensitivity, you could use regex:
if (/airport/i.test(this.value)) alert('true');
It becomes especially useful if you need to check for multiple variables instead of just airport:
if (/(airport|station|docks)/i.test(this.value)) alert('true');
http://jsfiddle.net/niklasvh/tHLdD/
normally you'd do it with either indexOf or split functions, e.g.
$("#textInput").val().split("specifictext").length > 0
there's also Contains Selector:
Description: Select all elements that contain the specified text.
which serves a slightly different purpose but may be of use to you
if($("#elementId").val().indexOf("airport") != -1) {
//Contains "airport"
}
The JavaScript indexOf function returns the index of the first occurence of the specified string. If the string is not found, it returns -1.
Don't really know if it's the best way.. but
function findInpWithTxt(txt) {
var t = null;
$("input[type=text]").each(function() {
if ($(this).val().indexOf(txt) >= 0) {
t = this;
return false;
}
});
return t;
}
this will return the input if found, null if not