I have 3 messages in variables.
var msg1 = "hello1";
var msg2 = "hello2";
var msg3 = "hello3";
I am trying to create a function that when i click it the first time it console.log(msg1), when i click it the second time it console.log(msg2), 3rd time console.log(msg3), 4th time console.log(msg1) and 5th msg2 etc.
$scope.clickMsg = function () {
console.log(msg1);
}
i've tried loops, timers etc but i could not make it work.
Does anyone know how to do this?
Use an array instead, and it's a bit easier, you'd just increment a number on each click, and use that number to select the item from the array
var msg = [
"hello1",
"hello2",
"hello3"
];
var i = 0;
var $scope = {};
$scope.clickMsg = function () {
console.log( msg[i] );
i++; // increment
if (i === msg.length) i = 0; // reset when end is reached
}
document.getElementById('test').addEventListener('click', $scope.clickMsg)
<button id="test">Click</button>
ES6 Generators based version:
var messages = (function*() {
for(;;) { yield msg1; yield msg2; yield msg3; }
})()
$scope.clickMsg = function () {
console.log(messages.next().value);
}
Unlike other answers, does not require you to use a different datatype and will also work for the locally scoped variables (i.e. non-window scoped variables).
Try It Online !
There are a few ways to do this in terms of accessing the string, I'd recommend putting them into an array rather than accessing the global/scoped object but it's up to you. Anyway on to the code.
var messagesArray = ["hello1", "hello2", "hello3"];
var messagesObject = {
msg1: "hello1",
msg2: "hello2",
msg3: "hello3"
}
var counter = 0;
function LogMessage() {
console.log(messagesArray[counter % 3]);
console.log(messagesObject["msg" + (counter % 3 + 1)]);
counter++
}
<button onclick="LogMessage()">Click Me</button>
Simply use with increment value like this
var msg1 = "hello1";
var msg2 = "hello2";
var msg3 = "hello3";
var c = 1;
$scope.clickMsg = function () {
c = c > 3 ? 1 : c;
console.log(window['msg'+c])
c++;
}
Working snippet
var msg1 = "hello1";
var msg2 = "hello2";
var msg3 = "hello3";
var c = 1;
var $scope={} //for testing
$scope.clickMsg = function () {
c = c > 3 ? 1 : c;
console.log(window['msg'+c])
c++;
}
function check(){ //for testing
$scope.clickMsg();
}
<button onclick="check()">click</button>
The alternative is using scopes, defining them as
this["msg"+i] = "some stuff";
and retrieving them as
this.msg0;
just do something like this, will work for you, make sure you reset it back if needed or do something, otherwise after first loop, you get undefined:
var msgs = ["hello1","hello2","hello3"], i=0;
$scope.clickMsg = function() { //angular $scope for example
console.log(msgs[i]);
if(i < msgs.length-1) {
i++;
} else {
i=0; //reset the loop
}
}
Related
I'm just writing a very simple function in javascript to calculate a factorial. I understand that in javascript you can assign a function to a variable.
So I have tried this on an online compiler (https://repl.it/languages/javascript) and this is what my code looks like
var mynum = prompt("Enter a number", "<enter a number>");
var answer;
if (isNaN(mynum)){
console.log(mynum +" is not a number");
}
else{
console.log("You entered "+mynum);
answer = function (mynum){
var i = mynum-1;
var temp = mynum;
while(i>0){
temp = temp*i;
i--;
}
return temp;
};
console.log("the factorial of "+mynum+" is "+answer);
}
But when I run this the output keeps including the whole function as "answer"
You entered 23
the factorial of 23 is function (mynum) {var _loopStart = Date.now(),_loopIt = 0;
var i = mynum - 1;
var temp = mynum;setTimeout(function () {_loopStart = Infinity;});
while (i > 0) {if (++_loopIt > 5000 && Date.now() - _loopStart > 150) throw new RangeError("Potential infinite loop. You can disable this from settings.");
temp = temp * i;
i--;
}
return temp;
}
However i don't have this issue when i create the function and then call it separately (something like answer = function(mynum).
Can anyone please let me know why this is happening?
Thanks!
Assigning a function to a variable is different from assigning its evaluation.
In your case, you have two solutions available :
Make an effective call to your assigned function at logging time:
console.log("the factorial of "+mynum+" is "+answer(mynum));
Make an effective call to your assigned function at assignation time:
answer = (function (mynum){
var i = mynum-1;
var temp = mynum;
while(i > 0) {
temp = temp*i;
i--;
}
return temp;
}(mynum));
Both solutions are quite equivalent for your specific situation.
Why?
Because declaring a function like so:
var func = function () {
console.log("Hello!");
};
Or like so:
function func () {
console.log("Hello!");
};
Has little difference
As pointed out, you have to call it as a function.
var mynum = prompt("Enter a number", "<enter a number>");
var answer;
if (isNaN(mynum)){
console.log(mynum +" is not a number");
}
else{
console.log("You entered "+mynum);
answer = function (mynum){
var i = mynum-1;
var temp = mynum;
while(i>0){
temp = temp*i;
i--;
}
return temp;
};
console.log("the factorial of "+mynum+" is "+answer (mynum));
}
Alternatively, you could use IIEF(mmediately invoked function expression):
var mynum = prompt("Enter a number", "<enter a number>");
var answer;
if (isNaN(mynum)){
console.log(mynum +" is not a number");
}
else{
console.log("You entered "+mynum);
answer = (function (mynum){
var i = mynum-1;
var temp = mynum;
while(i>0){
temp = temp*i;
i--;
}
return temp;
})(mynum);
console.log("the factorial of "+mynum+" is "+answer);
}
Note that I've added a parenthesis around your function and passed in arguments. That's how you can immediately invoke functions.
When you return a function in javascript such as answer(). You must call it as such.
console.log("the factorial of "+mynum+" is "+answer(mynum));
You need to use the function that you wrote by calling it i.e
function add (a,b) {
return a + b;
}
add(1,2);
I'm trying to learn Javascript and so I made a little code, but there is something wrong with it that I can
var array = new Array("Apple","Mangosteen","Durian","Pineapples");
...
...
function B() {
...
...
var BP = $("<p></p>");
BP.text("Click \"x\" on items to be removed").append("<br/>");
for (i=0;i<array.length;i++) {
var f = array[i];
var F = $("<div></div>");
F.attr({"class":"f"});
var N = $("<span></span>");
N.attr({"class":"n"});
N.text(f);
var d = $("<span></span>");
d.attr({"class":"cc sl"});
d.bind("click", function(e){
e.stopPropagation();
e.preventDefault();
IR(f,F);
});
d.html("×");
...
...
}
function IR(f,F) {
var a = array.indexOf(f);
array.splice(a,1);
F.remove();
}
When I added console.log(f); in function IR(), the value passed will always be "Pineapples", regardless if I'm clicking "x" on "Apples" or "Durian", the f value passed will always be "Pineapples". What is wrong with it?
You call a function inside a for loop - something you can read more about here JavaScript closure inside loops – simple practical example.
For now, if you're using ES6. The easiest way to solve it will be using let in the for loop.
for (let i=0;i<array.length;i++) { ...... }
Or else, use Array.forEach() instead of the for loop.
In your case it should be something like
array.forEach(function(fruit) {
var f = fruit;
var F = $("<div></div>");
F.attr({"class":"f"});
var N = $("<span></span>");
N.attr({"class":"n"});
N.text(c);
var d = $("<span></span>");
d.attr({"class":"cc sl"});
d.bind("click", function(e){
e.stopPropagation();
e.preventDefault();
IR(f,F);
});
d.html("×");
...
...
});
its because the scope of variable "i" is global, so var f = array[i]; will result in var f = array[3]; so you will get only "Pineapples".
I will give you a simple sample code to understand the issue. please run below code.
<script>
var funcs = [];
for (var i = 0; i < 3; i++) { // let's create 3 functions
funcs[i] = function() { // and store them in funcs
console.log("My value: " + i); // each should log its value.
};
}
for (var j = 0; j < 3; j++) {
funcs[j](); // and now let's run each one to see
}
</script>
you will get only 3 because "i" is in global scope.
When you declare a variable using var it will be declared within a scope of the function. That's why when you click 'x' javascript will pass to the IR function the last value of the variables - "Pineapples" and Pineapples's div. If you want to declare a variable within the 'for' cycle scope, use let. In this case, in every loop of 'for' cycle javascript will create a new variables f and F.
var array = new Array("Apple","Mangosteen","Durian","Pineapples");
function B() {
var BP = $("<div></div>");
BP.text("Click \"x\" on items to be removed").append("<br/>");
for (var i=0;i<array.length;i++) {
let f = array[i];
let F = $("<div></div>");
F.attr({"class":"f"});
var N = $("<span></span>");
N.attr({"class":"n"});
N.text(f);
var d = $("<span></span>");
d.attr({"class":"cc sl"});
d.bind("click", function(e){
e.stopPropagation();
e.preventDefault();
IR(f,F);
});
d.html("×");
F.append(N).append(d)
BP.append(F)
}
}
function IR(f,F) {
var a = array.indexOf(f);
array.splice(a,1);
F.remove();
}
i am trying to count how many times a letter appear in a string. This is my code:
var myFunc = function(inside) {
count = 0;
for (var i=0;i<inside.length;i++) {
if(inside[i]==="a") {
count+=1;
}
return count;
};
};
console.log(myFunc("hai, okay"));
var myFunc = function(inside) {
count = 0;
for (var i=0;i<inside.length;i++) {
if(inside[i]=="a") {
count+=1;
}
//return should not come here
};
return count;
};
console.log(myFunc("hai, okay"));
or u can use this also
var myFunc = function(inside) {
return (inside.match(new RegExp("a", "g"))).length;
}
console.log(myFunc("hai, okay"));
Your code is not giving correct result since it has a return statement inside a for loop so it will return after first iteration and will return 0. You can simply put the return outside for loop to make it work.
You can also simply change your method to
var myFunc = function(inside, character)
{
return inside.split( character ).length - 1;
};
console.log(myFunc("hai, okay"), "a");
How many letters? As in "Abba" would be 2 letters, namely "a" and "b"?
var letter_counts = function(txt) {
var res = {};
for (var i=0;i<txt.length;i++) {
var c = txt[i].toLowerCase();
res[c] = ( res[c] ? res[c] : 0 ) + 1;
};
return res;
};
var letter_cnts = letter_counts("Abba");
// Object {a: 2, b: 2}
letter_cnts["a"]; // == 2
letter_cnts["b"]; // == 2
What about
var countAs = inside.replace(/[^a]/g, '').length;
Reason: elminate all char's unwanted and take the length of the rest.
Warpped:
function howMany(inside, theChar)
{
var reg = new RegExp("[^" + theChar + "]","g");
return inside.replace(reg, '').length;
}
I have the following code:
page.listSuccess = function (data, status, xhr) {
console.log(data);
if (data && data.items) {
var itemsQty = Math.ceil(data.items.length / 3);
for (var index = 0; index < itemsQty; index++) {
var itemData = {};
var itemClone = page.insertItemDOM(itemData);
if (index == 0) {
itemClone.addClass("active");
console.log(itemClone);
}
}
}
for (var index = 0; index < data.items.length; index++) {
var testimonialData = {}
testimonialData.title = data.items[index].title;
testimonialData.body = data.items[index].body;
testimonialData.starRating = data.items[index].starRating;
testimonialData.id = data.items[index].id;
page.insertTestimonialDOM(testimonialData);
}
}
At the moment, this code inserts all(5) my testimonials on one page. I need three per page, but I'm unsure as to how to go about it.
itemClone = a page on the carousel
testimonialData = a testimonial
insertItemDOM function =
page.insertItemDOM = function (itemData) {
var newItem = $($("#itemTemplate").html()).clone();
var targetLoc = $('.carousel-inner');
targetLoc.attr("data-target", "true");
targetLoc.append(newItem);
return newItem;
}
insertTestimonialDOM function =
page.insertTestimonialDOM = function (testimonialData) {
var newTemplate = $($("#testimonialTemplate").html()).clone();
newTemplate.find('.title').html(testimonialData.title);
newTemplate.find('.body').html(testimonialData.body);
newTemplate.find('.starRating').html(testimonialData.starRating);
var targetLoc = $('.carousel-inner');
targetLoc.attr("data-target", "true");
targetLoc.append(newTemplate);
}
Let me explain the concept for you. What you want is after every 3 loop execution the loop shall work it again and enter details in a new page.
Let's make two function.
var index;
var theinitial = function(z)
{
index = z
var counter = 1;
insertionfunction();
}
var insertionfunction = function()
{
for (var zzz = index; zzz < data.items.length; zzz++) {
if (counter <= 3)
{
itemClone = page.insertItemDOM(itemData);
}
else
{
theinitial(zzz);
}
}
Here the first request you make to 'theinitial function' with 1 as value of z then the function will call the insertion function and now the loop will run for 3 times then after three times the value of zzz is used to call the initial function again. Now your index is 4, hence the loop will start from 4th element and run for 3 more times as counter is reinitialized to 1.
I don't really know how your page insertion thing works therefore I am explaining the concept to you.
I'm trying to execute a rotating banner (Calling it through an array). I set an interval but the image only shows after 10 seconds (10000) and only then begins the rotation. I removed the cluttered HTML of the array, but here's the rest of it:
var current = 0;
var banners = new Array();
banners[0]=;
banners[1]=;
banners[2]=;
banners[3]=;
var myTimeout = setInterval("rotater()",10000);
function rotater() {
document.getElementById("placeholderlayer").innerHTML=banners[current];
if(current==banners.length-1){
current = 1;
}else{
current += 1;
}
}
window.onload = rotater();
window.onload = rotater;
is the correct syntax. You don't want to call the function. However, the bulletproof solution is rather this:
onload = function() {
rotater();
window.myTimeout = setInterval(rotater, 10000); // Never pass a string to `setInterval`.
};
ProTip™: Don't use new Array(), use an array literal. For example, this:
var arr = new Array();
arr[0] = 'Hello';
arr[1] = 'world!';
Should be written as:
var arr = ['Hello', 'world!'];
Just a comment:
Instead of:
if(current==banners.length-1) {
current = 1;
} else {
current += 1;
}
you can do:
current = ++current % banners.length;