Create variables on the fly - javascript

Im creating code snippets dynamicly:
var gg = setInterval(function() {
if($('p:visible').length > 0) {
$('p').trigger('click') ;
clearInterval(gg);
}
},500);
The code works. The problem is that I create the same code snippets with different selectors:
var gg = setInterval(function() {
if($('input:visible').length > 0) {
$('input').trigger('focus') ;
clearInterval(gg);
}
},500);
So when I put(create) these codes together, the whole thing goes in to some loop and it doesn't work anymore, take a look at this example: JsFiddle
The problem is that I assign the same variable (gg) to the codes. So my question is: How do I create different variables every time I create these code snippets? I tried some things with var x=x++ but I can't get it to work.

Here are two ways of accomplishing what you want to do (dynamic variables). The first is evaling a string.
(There are a ton of articles out there that will explain why this is bad. But, for the sake of being complete, I'm providing this example...maybe as an example of what not to do ;)
A function that creates variables based on a string you pass in, and then using that eval'd variable would work. Something like:
function varMaker(str){
// Nothing fancy...
var token = Math.floor(new Date().getTime() * Math.random(10));
// Defining variable with no var for global scope (bad)
return eval(str + '_' + token + ' = undefined;');
}
Here's a quick/dirty fiddle example (no function maker, just an eval'd string): http://jsfiddle.net/D3wZ7/
The second, cleaner approach is using square bracket notation (and what I would recommend). Something like this:
window['gg' + randomized_string] = setInterval(..)
Note: Once you've defined the variable, you can reference it as you normally would as such:
window['my_cool_variable' + 1] = "stack";
alert(my_cool_variable1); //alerts "stack"
Here's a fiddle demonstrating this: http://jsfiddle.net/ZmGH5/
Good luck!

Simply put the snippets in anonym wrapper functions so that the variable gg is not global anymore:
(function(){
var gg = setInterval(function() {
if($('input:visible').length > 0) {
$('input').trigger('focus') ;
clearInterval(gg);
}
},500);
})();
(function(){
var gg = setInterval(function() {
if($('p:visible').length > 0) {
$('p').trigger('click') ;
clearInterval(gg);
}
},500);
})();
(These Functions are executed automatically...)

var gg= [];
gg[0] = setInterval(function() {
if($('p:visible').length > 0) {
$('p').trigger('click') ;
clearInterval(gg[0]);
}
},500);
gg[1] = setInterval(function() {
if($('input:visible').length > 0) {
$('input').trigger('focus') ;
clearInterval(gg[1]);
}
},500);
so go on like this way. You can create lots of by using array.

in that other snippet change
var gg =...
to var hh =...
and then clearInterval(hh)

Related

Creating a for loop that loops over and over =

So I have a weird problem (as I can do this using dummy code, but cannot make it work in my actual code) -
The concept is simple - I need a for loop that upon hitting its max "I" number reverts "I" to 0 again and creates a loop over and over -
DUMMY CODE:
for(i=0;i<10;i++){
console.log(i);
if(i === 10){
i = 0
}
}
Now for the longer code (sorry)
function reviewF(){
// add ID to each of the objects
reviews.forEach((e, i)=>{
e.id = i
})
// get the elements to be populated on page
var name = document.querySelector('p.name');
var date = document.querySelector('p.date');
var rating = document.querySelector('.rating_stars');
var review = document.querySelector('p.review_content_text');
// reverse the array - so the newest reviews are shown first (this is due to how the reviews where downloaded)
var reviewBack = reviews.slice(0).reverse();
// start the loop - go over each array - take its details and apply it to the elements
/**
* THIS IS WHAT I WOULD LIKE TO LOOP OVER FOREVER
*
* **/
for (let i = 0; i < reviewBack.length; i++) {
(function(index) {
setTimeout(function() {
// document.getElementById('reviews').classList.remove('slideOut')
name.classList.remove('slideOut')
date.classList.remove('slideOut')
rating.classList.remove('slideOut')
review.classList.remove('slideOut')
name.classList.add('slideIn')
date.classList.add('slideIn')
rating.classList.add('slideIn')
review.classList.add('slideIn')
name.innerHTML = reviewBack[i].aditional_info_name;
date.innerHTML = reviewBack[i].Date;
rating.innerHTML = '';
review.innerHTML = reviewBack[i].aditional_info_short_testimonial;
if(reviewBack[i].aditional_info_short_testimonial === 'none'){
reviewBack.innerHTML='';
}
var numberOfStars = reviewBack[i].aditional_info_rating;
for(i=0;i<numberOfStars;i++){
var star = document.createElement('p');
star.className="stars";
rating.appendChild(star);
}
setTimeout(function(){
// document.getElementById('reviews').classList.add('slideOut')
name.classList.add('slideOut')
date.classList.add('slideOut')
rating.classList.add('slideOut')
review.classList.add('slideOut')
},9600)
}, i * 10000)
})(i);
// should create a infinite loop
}
console.log('Loop A')
}
// both functions are running as they should but the time out function for the delay of the transition is not?
reviewF();
EDITS >>>>>>>>
Ok so I have found a hack and slash way to fix the issue - but its not dry code and not good code but it works.....
this might make the desiered effect easier to understand
reviewF(); // <<< this is the init function
// this init2 function for the reviews waits until the reviews have run then
// calls it again
setTimeout(function(){
reviewF();
}, reviews.length*1000)
// this version of the innit doubles the number of reviews and calls it after that amount of time
setTimeout(function(){
reviewF();
}, (reviews.length*2)*1000)
From trying a bunch of different methods to solve this issue something I noticed was when I placed a console.log('Finished') at the end of the function and called it twice in a row (trying to stack the functions running..... yes I know a horrid and blunt way to try and solve the issue but I had gotten to that point) - it called by console.log's while the function was still running (i.e. the set time out section had not finished) - could this have something to do with it.
My apologies for the rough code.
Any help here would be really great as my own attempts to solve this have fallen short and I believe I might have missed something in how the code runs?
Warm regards,
W
Why not simply nest this for loop inside a do/while?
var looping = True
do {
for(i=0;i<10;i++){
console.log(i);
}
if (someEndCondition) {
looping = False;
}
}
while (looping);
I would think that resetting your loop would be as simple as setting "i = 0" like in the dummy code. So try putting the following into your code at the end of the for loop:
if(i === 10){
i = 0;
}

Repeating Value and Replacing Value with JS

Newbie in JS here. I'm having trouble replacing and repeating the value from the function. Here's the code:
function Phone(ring) {
this.ring = ring;
}
function updateRing(newRing) {
this.newRing = ring;
}
var samsung = new Phone('Chim');
samsung.ring(2); // Needs to compute to "Chim, Chim"
var htc = new Phone('Dada');
htc.ring(3); // Needs to compute to "Dada, Dada, Dada"
htc.updateRing('Riri');
htc.ring(1); // Needs to compute to "Riri"
For the repeat value for the first function, I tried using this.repeat but it didn't work inside the Phone function.
For the updateRing function, I couldn't get the code to replace the this.ring.
I stripped down all the useless code I had written. Thanks in advance for any help.
You can repeat strings with string.repeat()
let a = "ring"
console.log(a.repeat(2))
But to get the comma separator to work cleanly you can make a disposable array and join() is with a comma.
let ringString = Array(3).fill("ring").join(", ")
console.log(ringString)
For the others, you probably want to use classes, which are pretty easy, but don't run on IE without a ployfill. Or prototypes, which can be a little confusing at first. Here's an example using prototypes to define methods on your Phone object:
function Phone(ring) {
// changed to ring_tone too prevent clash with this.ring method
this.ring_tone = ring;
}
// you need to define these on the prototype to you can use `this`
Phone.prototype.updateRing = function(newRing) {
// don't need to define a this.newRing, just update the ring
this.ring_tone = newRing;
}
Phone.prototype.ring = function(n) {
return new Array(n).fill(this.ring_tone).join(', ')
}
var samsung = new Phone('Chim');
console.log(samsung.ring(2)); // Needs to compute to "Chim, Chim"
var htc = new Phone('Dada');
console.log(htc.ring(3)); // Needs to compute to "Dada, Dada, Dada"
htc.updateRing('Riri');
console.log(htc.ring(1)); // Needs to compute to "Riri"
1) You're calling samsung.ring as a function, even though it's just an instance variable of Phone.
2) The reason why this.repeat didn't work is because repeat isn't a method of "this," which refers to Phone.
Try this instead:
var samsung = new Phone('Chim');
samsung.ring.repeat(2);
var htc = new Phone('Dada');
htc.ring.repeat(3);
Maybe try this:
class Phone {
constructor(sound) {
this.sound = sound;
}
ring(number) {
var i;
for (i = 0; i < number; i++) {
console.log(this.sound + ", ");
}
}
updateRing(newSound) {
this.sound = newSound;
}
}
var samsung = new Phone('Chim');
samsung.ring(2);
samsung.updateRing('Riri');
samsung.ring(1);
Codepen - https://codepen.io/anon/pen/MGRJOB?editors=0010

Can I use a string variable in document.getElementById()?

here is my code:
function figureSelector () {
document.getElementById("rook").onclick = function () {
curr = '"rook"';
};
};
function moveLine(){
document.getElementById("upButton").onclick = function() {
document.getElementById(curr).style.top = document.getElementById(curr).offsetTop - getPix() * 62 + "px";
counter= counter + getPix();
};
I want to write an universal function for a chess piece to move. All I want is, when one clicks the chess piece, and then presses the up button, it must go up.
Yes you can use String variable:
HTML:
<div id="name" style="width:300px;height:300px;background:red"></div>
javascript:
var b = 'name';
document.getElementById(b).innerHTML = 'none';
jsfiddle here
Yes, you can.
Just use
curr = 'rook';
(without the extra quotes)
You can even do stuff like this:
function mark(yy) {
for (var ii = 0; ii < 7; ii++ ) {
if ( ii == yy ) {
document.getElementById("b"+ii).style.fontWeight = "bold";
}
...
But be careful of your loop limits to be sure you have a matching id. I just spent hours trying to figure out why ("b"+ii) was getting error and finally realized that the error was being caused by exactly that. duh...
Yes, Mate, you can.
You can use a variable as the argument for any function. That's just how functions work -- they don't care where the argument comes from. You should define curr outside those functions.

Using eval to assign a variable to a method. How else should I do it?

I am using a method to accept a portion of an element's ID and use that to determine which url path I need to pass to a method. In my case this is used by a click event on a button that could be attached to any one of a number of grids so I need to know which grid I am on in order to know what data to reload:
jQuery('.reset').click(function(e) {
e.preventDefault();
jQuery('#' + grid_id + '_mnf').toggle();
jQuery('#' + grid_id + '_mnfall > .instance').each(function () {
jQuery(this).removeAttr("checked");
});
var url = eval(grid_id + '_url');
jQuery('#foo').setGridParam({url:url}).trigger('reloadGrid');
});
The possible urls are defined as variables so I have something like:
var foo_url = url_path + '?input=moduleone&param=1';
var bar_url = url_path + '?input=moduleone&param=2';
This means that in the setGridParam method above the url value will be one of these vars. If I simply do:
var url = grid_id + '_url'; //note I'm not using eval here
The value passed to setGridParam will not work.
If I don't use eval like I do above the url will not work. Why? What is going on here? What else should I do since "eval is evil"?
In my mind, without using eval, I am passing the url like:
jQuery('#foo').setGridParam({url:foo_url}).trigger('reloadGrid');
but this fails so apparently eval is required here?
Because I am sure this is too rigid and clunky of a way to do this and in case anyone wants to see it (and perhaps suggest how I am doing this wrong?), here is how I am getting that grid_id:
// ex. id='foo_filter'
var source = $(this).parent().parent().attr('id').split('_');
var parsed_source = source.splice(1, source.length + 1);
grid_id_portion = '';
for (var i = 0; i < parsed_source.length; i++) {
grid_id += parsed_source[i];
if(i < parsed_source.length - 1){
grid_id += '_';
}
}
Some issues I see... I have to define the urls as variables for each grid. This is quite inflexible, yes? Those urls are pretty similar as well so defining a bunch of them seems inefficient. Also, what if someone crafts a special chunk of code to insert as the ID that I am breaking apart to pass to eval. That could be bad news, yes? Any suggestions on how to improve on this would be greatly appreciated.
Use a map to store URLs, not local variables.
var URLs = {
foo: url_path + '?input=moduleone&param=1',
bar: url_path + '?input=moduleone&param=2'
};
jQuery('.reset').click(function() {
//do stuff...
var url = URLs[grid_id];
jQuery('#foo').setGridParam({url:url}).trigger('reloadGrid');
});

Javascript setTimeout Parameter Issue (The I'm Using an Anonymous Function Version)

I can't believe that I'm having an issue with this. My setTimeout is:
setTimeout(function(){showContent(entries, 0);}, 500);
I also tried:
(function(entries, index){
clear_show_content = setTimeout(function(){
showContent(entries, index);
}, 500);
})(entries, 0);
and in showContent(entries, index) index is undefined. Please tell me I'm just missing something obvious here.
EDIT: This code is causing so many problems tonight :)
var clear_show_content;
function showContent(json){
var entries = json;
$('#content').html('');
if(checkIfNoneEntered(entries))
$('#content').append('<div class="entry">No Alumni Entered Yet!</div>');
else if(checkIfNoMatches(entries))
$('#content').append('<div class="entry">No Matches Found!</div>');
else if(checkIfError(entries))
$('#content').append('<div class="entry">There was an error!</div>');
else {
clearTimeout(clear_show_content);
$('#content').append('<table border="2" id="content_table" width="50%">');
var filler = '<img width="1" height="1" />';
clear_show_content = setTimeout((function(){showContent(entries, 0);}),
500);
}
}
function showContent(entries, index){
if(index < 0)
return;
stop = index + 10 > entries.alumnus.length ? entries.alumnus.length : 10;
start = new Date();
for(allIndex = index; allIndex < stop; allIndex++){
}//This is where it becomes proprietary, but I highly doubt the issue is after here
EDIT 2: Here's a jsFiddle of the issue. It's not working on my browser (Chrome 16) and I don't currently have access to any other browser. I don't think that's the issue though, as I've written code like this hundreds of times. http://jsfiddle.net/eygraber/NduqY/1/
You're defining your showContent function twice...
Both your functions are called 'showContent' which means when you try to call the first one, you're really calling the second one because the first is overwritten.
When you check if index is undefined, check what's in entries. I bet it's the json you meant to pass to the first function.

Categories