I'm trying to get the first function, to run repeatedly. Like it does in the second function. Where should I take a look?
(function printLetterByLetter() {
var i = 0;
var destination = "comment";
var RandomComment = [
"Did you choose that outfit?"
, "I like trains."];
var message = RandomComment[Math.floor(Math.random() * RandomComment.length)];
var typewriter = function () {
document.getElementById(destination).innerHTML += message.charAt(i);
i++;
if (i > message.length) {
clearInterval(typespeed);
}
}
var speed = 60;
var typespeed = setInterval(typewriter, speed)
}());
(function printLetterByLetter() {
var destination = "comment";
var frequency = 1000;
var RandomComment = [
"Did you choose that outfit?"
, "I like trains."];
var RandomCommentTimer = setInterval(function () {
var message = RandomComment[Math.floor(Math.random() * RandomComment.length)];
}, frequency)
}());
So what i'm trying to do is to make one function/module that types out a random comment at a set speed(first function). And after a set time the comment will disappear and a new comment will be typed out(second function). And like the second function this will go on.
So far I haven't made it work myself so I thought: let's see if anyone can help me on stackoverflow.
If anyone can give a tip on where to take a look, that is also most welcome.
You could set and alter the function parameters outside of the function then access them inside. Caveat is that you can't put var in front when setting them. Not putting var in front makes it accessible outside of the current scope.
destination = "comment";
frequency = 6000;
(function printLetterByLetter() {
//now you have access to destination and frequency as they are defined before the function is called
var RandomComment = [
"Did you choose that outfit?"
, "I like trains."];
var RandomCommentTimer = setInterval(function () {
var message = RandomComment[Math.floor(Math.random() * RandomComment.length)];
document.getElementById(destination).innerHTML = message;
}, frequency)
}());
Related
I want to track the content consumption behavior on our SPA blog website. I refer to this blog post and modify its example to set a custom HTML tag in GTM like this, and the following tag will be triggered after a gtm_history event is triggered on blog article pages.
var contentContainer = "my article class";
var wordsPerMinute = 250;
var is_error = false;
var event_timer_reached = 'content_time_reached';
// Calculated Variables
var contentEl = document.querySelector(contentContainer);
if (contentEl == null) { is_error = true; }
/**
* Start content consumption plugin
*/
function initContentConsumption() {
var timeToRead = null;
var interval = null;
var contentEl = document.querySelectorAll(contentContainer);
var wordContentCount = wordCount(contentEl);
if (contentEl && wordContentCount) {
// Time to read by wordsPerMinute
timeToRead = (wordContentCount / wordsPerMinute).toFixed(2);
interval = timeToRead * 60 * 1000;
pageReadTimer(interval);
}
}
function pageReadTimer(interval) {
window.setTimeout(function() {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ 'event': event_timer_reached });
}
, interval);
}
function wordCount(words) {
var count = 0;
for (var i = 0; i < words.length; i++) {
var cleanWords = words[i].innerText.replace(/\n\n/g, " ");
cleanWords = cleanWords.replace(/\n|\t/g, " ");
count += cleanWords.split(" ").length;
}
return count;
}
if(is_error==false){initContentConsumption()}
I expect the code to work as follows:
Calculate the characters of the blog post and suggest a minimal reading time
Push a "content-time-reached" event only when the reader stays on the page over the minimal reading time
So far, the code works fine if readers do spend more time reading a specific post. However, if it is not the case, the event might be pushed to the wrong page.
Say a reader selects post-A with the suggested reading time of 45 sec. If he only stays on the post for 30 seconds, goes to another Post B (say post-B has the suggested reading time of 60 seconds), and stays for 15 seconds, the event "content-time-reached" will still be fired. How it should work is that the event should not be pushed on either post-A or post-B since the reader doesn't stay longer on the blog post pages respectively than each post's suggested reading time.
I know the issue is that I use the "setTimeout" function to push the event, and it will push it whenever a reader stays on the site longer than any single blog's suggested reading time. I've changed my scripts based on the guidance of this post, added a new data layer variable named "custom.timer.running," and changed the "setTimeout" to "setInterval" and "clearInterval." However, it turned out that the tag was not fired at all.
var contentContainer = "my article class";
var wordsPerMinute = 250;
var is_error = false;
var event_timer_reached = 'content_time_reached';
var timerNumber = 1;
var limit = 1;
/**
* Start content consumption plugin
*/
function initContentConsumption() {
var timeToRead = null;
var interval = null;
var contentEl = document.querySelectorAll(contentContainer);
var wordContentCount = wordCount(contentEl);
if (contentEl && wordContentCount) {
// Time to read by wordsPerMinute
timeToRead = (wordContentCount / wordsPerMinute).toFixed(2);
interval = timeToRead * 60 * 1000;
pageReadTimer(interval);
}
}
function pageReadTimer(interval) {
var fireTimer = function() {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ 'event': event_timer_reached,
'custom.timer.running' : 'false'});
timerNumber += 1;
if(limit < timerNumber){
window.clearInterval(timerId);}
}
if ({{custom.timer.running}} == 'false') {
window.dataLayer.push({ 'custom.timer.running' : 'true'});
var timerId = window.setInterval(fireTimer, interval); }
}
function wordCount(words) {
var count = 0;
for (var i = 0; i < words.length; i++) {
var cleanWords = words[i].innerText.replace(/\n\n/g, " ");
cleanWords = cleanWords.replace(/\n|\t/g, " ");
count += cleanWords.split(" ").length;
}
return count;
}
initContentConsumption()
I'm working on trying to create a random image generator that will show a random image in Javascript. I've been able to make it show a random image via the Javascript math and using random variables. But sadly I'm still yet to be eligible to make my code repeat itself.
I know its probably very simplistic but as you know, we all start from somewhere. I've tried my best to compact my code and I have looked at other stackoverflow recourses but im still in no luck.
A quick overview of what happens, you are meant to be able to press a button and then, a selected random image is replaced by the current one.
What I want: to be able to press a button and then it will proceed to cycle through the random images 'x' times.
My code:
function imgRandom() {
var myImages1 = new Array();
myImages1[1] = "images/Random/Icon1.png";
myImages1[2] = "images/Random/Icon2.png";
myImages1[3] = "images/Random/Icon3.png";
myImages1[4] = "images/Random/Icon4.png";
myImages1[5] = "images/Random/Icon5.png";
myImages1[6] = "images/Random/Icon6.png";
myImages1[7] = "images/Random/Icon7.png";
myImages1[8] = "images/Random/Icon8.png";
myImages1[9] = "images/Random/Icon9.png";
myImages1[10] = "images/Random/Icon10.png";
myImages1[11] = "images/Random/Icon11.png";
myImages1[12] = "images/Random/Icon12.png";
myImages1[13] = "images/Random/Icon13.png";
myImages1[14] = "images/Random/Icon14.png";
myImages1[15] = "images/Random/Icon15.png";
myImages1[16] = "images/Random/Icon16.png";
myImages1[17] = "images/Random/Icon17.png";
myImages1[18] = "images/Random/Icon18.png";
myImages1[19] = "images/Random/Icon19.png";
myImages1[20] = "images/Random/Icon20.png";
myImages1[21] = "images/Random/Icon21.png";
myImages1[22] = "images/Random/Icon22.png";
myImages1[23] = "images/Random/Icon23.png";
var rnd = Math.floor(Math.random() * myImages1.length);
if (rnd == 0) {
rnd = 1;
}
document.getElementById("gen-img").src = myImages1[rnd];
}
<center>
<p>
<img id="gen-img" class="character-image" src="images/QuestionMark.png" style="width:180px;height:310px;">
</p>
<p>
<input type="button" class="button" value="Choose" onclick="setTimeout(imgRandom, 3000);" />
</p>
</center>
I hope this isn't too confusing, i'll be active for a long time if you're able to help! Thanks,
David.
I refactored your code a bit with an possible approach Here's the fiddle: https://jsfiddle.net/mrlew/d2py2jvb/
I commented with some explanations.
/* some flags you can set */
var timesTocycle = 10;
var totalImagesToCreate = 23;
var timeBetweenCycle = 3000;
/* global variables */
var allMyImages = [];
var timesCycled = 0;
/*
function to create your images path.
Called once when you load your page.
*/
function createMyImages(total) {
for (var i=0; i<total;i++) {
var imageNumber = i+1;
var path = getImagePath(imageNumber);
allMyImages.push(path);
}
}
/* separated your path getter */
function getImagePath(imageNumber) {
return "images/Random/Icon" + imageNumber + ".png";
}
/* this is the function called when you press the button and when one cycle ends */
function triggerRandomImage() {
if (timesCycled >= timesTocycle) return;
setTimeout(displayRandomImage, timeBetweenCycle);
}
/* random integer javascript function */
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
/* function called on setTimeout */
function displayRandomImage() {
var rnd = getRandomInt(0,allMyImages.length-1);
var imageToDisplayPath = allMyImages[rnd];
document.getElementById("gen-img").src = imageToDisplayPath;
timesCycled++;
triggerRandomImage();
/* debug info */
document.getElementById('info').innerText = "(showing: " + imageToDisplayPath + ", cycle: " + timesCycled + ", max: " + timesTocycle + ")";
}
/* call this function to populate the allMyImages array */
createMyImages(totalImagesToCreate);
I believe what you want is for loop. Let me demonstrate with your code:
var count = 10; //number of times to run the for loop
for (i = 0; i < count; i++){
var rnd = Math.floor(Math.random() * myImages1.length);
if (rnd == 0) {
rnd = 1;
}
document.getElementById("gen-img").src = myImages1[rnd];
}
The above code would run the randomizing bit 10 times (= 10 images). Now, I have not tested it yet, but I believe that the images would flash by really quickly. Also, unrelated to the question you may want to read about Javascript arrays.
I have two functions. In the first one I increase a variable by adding 100 to it and I put a setInterval so the funcion repeats itself after some time. The other function is a class, a contrusctor to create an object. I want this.x_origen to get increased by adding aumento to it after some time and repeat it. However what I'm getting here is that the first function increases aument and then it finishes and then the second function starts. How can I solve this?
var aument = 0;
function aumento(){
aument = aument + 100;
return aument;
}
setInterval(function () {aumento()}, 1000/50);
function create_class_brick (x_origen_in, y_origen_in, x_final_in, y_final_in, mi_estado, mi_velocidad, mi_id){
this.x_origen = x_origen_in + aumento();
this.y_origen = y_origen_in;
this.x_final = x_final_in + aumento();
this.y_final = y_final_in;
this.estado = mi_estado;
this.velocidad = mi_velocidad;
this.id_elemento = mi_id;
this.DESPLAZAR_LADRILLO = desplazar_ladrillo;
this.F0 = f0;
this.F2 = f2;
this.crear_ladrillo = crear_ladrillo;
this.obtener_x_origen_ladrillo = obtener_x_origen_ladrillo;
this.obtener_y_origen_ladrillo = obtener_y_origen_ladrillo;
this.obtener_x_final_ladrillo = obtener_x_final_ladrillo;
this.obtener_y_final_ladrillo = obtener_y_final_ladrillo;
}
An example on how to wait for the initial call:
function brick (x_origen_in){
this.x_origen = x_origen_in;
}
function aumento(brick){
console.log(brick.x_origen);
brick.x_origen += 100;
setTimeout(aumento.bind(this, brick), 500);
}
var brick = new brick(100);
aumento(brick);
http://jsfiddle.net/x6c08u39/
You can use Object.defineProperty to dynamically generate the value whenever it is accessed.
First, lets simplify the auto-incrementing of aument:
var aument = 0;
function aumento(){
aument += 100;
}
// The first argument for setInterval is the function to execute
// No need to figure out the interval value at runtime as there are no dynamic values
setInterval(aumento, 20); // 1000/50 === 20
Now lets make an object that will have a the correct value:
function create_class_brick (x_origen_in, y_origen_in, x_final_in, y_final_in, mi_estado, mi_velocidad, mi_id){
Object.defineProperty(this, 'x_origen', {
get: function () { return x_origen_in + aument; }
});
// Other stuff
// ...
}
A quick test:
> aument
34100
> var obj = new create_class_brick(23);
undefined
> obj.x_origen
161523
> obj.x_origen
167223
> obj.x_origen
172423
I have built this code using javascript that makes a few objects called monster. I then put those monsters in an array and finally am trying to call one of thous monsters to the console randomly. Unfortunately it displays in my console log as undefined. Any advice on how to get a random monster in the console log every time I refresh the page?
function Monster(type, level, mAttack, mAgility, mHP) {
this.type = type;
this.level = level;
this.mAttack = mAttack;
this.mAgility = mAgility;
this.mHP = mHP;
}
Monster.prototype.logInfo = function() {
console.log("I am a : ", this.type);
console.log("I am level : ", this.level);
console.log("I have the attack of : ", this.mAttack);
console.log("I have the agility : ", this.mAgility);
console.log("I have the health : ", this.mHP);
}
var troll = new Monster("troll", 1, 10, 10, 10);
var skeleton = new Monster("skeleton", 1, 10, 10, 10);
var slime = new Monster("slime", 1, 10, 10);
var boar = new Monster("boat", 1, 10, 10);
var monsterList = new Array();
monsterList[0] = troll;
monsterList[1] = skeleton;
monsterList[3] = slime;
monsterList[4] = boar;
var summonRandomMonster = function (){
monsterSummoner = monsterList[Math.floor(Math.random() * monsterList.length)];
}
console.log(monsterSummoner);
You create a function but never call it. Therefor monsterSummoner is never set.
// THIS IS NEVER CALLED
var summonRandomMonster = function (){
monsterSummoner = monsterList[Math.floor(Math.random() * monsterList.length)];
}
console.log(monsterSummoner);
Try this instead. Notice that now that the function is called the value is set.
var monsterSummoner;
var summonRandomMonster = function (){
monsterSummoner = monsterList[Math.floor(Math.random() * monsterList.length)];
}
summonRandomMonster();
console.log(monsterSummoner);
You're close... Change your last four lines as follows -
var monsterList = [troll,skeleton,slime,boar];
var summonRandomMonster = function (){
monsterSummoner = monsterList[Math.floor(Math.random() * monsterList.length)];
console.log(monsterSummoner);
}
for (var i = 0; i < 100; i++) {
summonRandomMonster();
}
There are atleast two problems in this code. The variable "monsterSummoner" is not defined, and the function "summonRandomMonster" is not called.
I am trying to adapt the really cool looking WebGL Story Sphere, source code and css here. There's one big problem: once you click on a news article, the text of the article in the popup is always the same. I want to modify the code so that when you click on an article, the right text appears in the popup.
I'm working from a set of article texts that I specify in the code, e.g. var captions = ["good","better","best"]. Though the article titles and images populate correctly in the popup, I can't get the text to do so. Can you help me?? Here's what I've got:
// function code
var passvar = null; // failed attempt to store texts for later
function initialize() {
math = tdl.math;
fast = tdl.fast;
canvas = document.getElementById("canvas");
g_fpsTimer = new tdl.fps.FPSTimer();
hack();
canvas.addEventListener("mousedown", handleMouseDown, false);
canvas.addEventListener("mousemove", handleMouseMove, false);
canvas.addEventListener("mouseup", handleMouseUp, false);
// Create a canvas 2d for making textures with text.
g_canvas2d = document.createElement('canvas');
window.two2w = window.two2h = g_tilesize;
g_canvas2d.width = two2w;
g_canvas2d.height = two2h;
g_ctx2d = g_canvas2d.getContext("2d");
window.gl = wu.create3DContext(canvas);
if (g_debug) {
gl = wd.makeDebugContext(gl, undefined, LogGLCall);
}
//gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, gl.TRUE);
// Here is where I specify article titles, images, captions
// Titles and images populate the popup correctly, captions don't...
var titles = ["a","b","c"];
var captions = ["good","better","best"];
var images = ['imagesphere/assets/1.jpg',
'imagesphere/assets/bp/2.png',
'imagesphere/assets/bp/3.png'
];
var headlines = titles.concat( titles);
var blurbs = captions.concat( captions);
var tmpImages = [];
var tmpHeadlines = [];
var tmpCaptions = [];
// make a bunch of textures.
for (var ii = 0; ii < g_imagesDownGrid; ++ii) {
var textures = [];
for (var jj = 0; jj < g_imagesAcrossGrid; ++jj) {
var imgTexture = new ImgTexture();
textures.push(imgTexture);
if (tmpImages.length == 0) {
tmpImages = images.slice();
}
if (tmpHeadlines.length == 0) {
tmpHeadlines = headlines.slice();
}
if (tmpCaptions.length == 0) {
tmpCaptions = blurbs.slice();
}
var rando = math.randomInt(tmpImages.length);
var img = tmpImages.splice(rando, 1)[0];
var headline = tmpHeadlines.splice(rando, 1)[0];
var caption = tmpCaptions.splice(rando, 1)[0];
passvar = caption;
if (img.indexOf('videoplay.jpg') > -1){
window.vidtexture = imgTexture;
images = images.slice(1); // dont use that thumb again.
headlines = 'WebGL Brings Video To the Party as Well'
}
imgTexture.load(img, /* "[" + jj + "/" + ii + "]" + */ headline);
}
g_textures.push(textures);
}
// And here's where I try to put this in a popup, finally
// But passvar, the stored article text, never refreshes!!!
<div id="story" class="prettybox" style="display:none">
<img class="close" src="imagesphere/assets/close.png">
<div id="storyinner">
<input id = "mytext">
<script>document.getElementById("mytext").value = passvar;</script>
</div>
</div>
And here is my click handler code:
function sphereClick(e){
window.console && console.log('click!', e, e.timeStamp);
var selected = g_textures[sel.y][sel.x];
window.selected = selected;
animateGL('eyeRadius', glProp('eyeRadius'), 4, 500);
var wwidth = $(window).width(),
wheight = $(window).height(),
story = $('#story').width( ~~(wwidth / 7 * 4) ).height( ~~(wheight / 6 * 5) ),
width = story.width(),
height = story.height(),
miniwidth = 30;
story.detach()
.find('#storyinner').find('h3,img,caption').remove().end().end()
.show();
story.css({
left : e.pageX,
top : e.pageY,
marginLeft : - width / 2,
marginTop : - height / 2
}).appendTo($body); // we remove and put back on the DOM to reset it to the correct position.
$('style.anim.story').remove();
$('<style class="anim story">')
.text( '.storyopen #story { left : ' + (wwidth / 3 * 2) + 'px !important; top : ' + wheight / 2 + 'px !important; }' )
.appendTo($body);
$(selected.img).prependTo('#storyinner').parent();
$('<h3>').text(selected.msg.replace(/\(.*/,'')).prependTo('#storyinner');
$body.addClass('storyopen');
} // eo sphereClick()
There's a lot wrong here, but here's a start. It won't solve your problem, but it will help you avoid issues like this.
var passvar = null; is a global variable.
Your loop for (var ii = 0; ... sets that global variable to a new value on every iteration.
Later, you click something and the global variable passvar is never changed.
If you want to use this pattern, you need to set passvar from your click handler so it has the value that was clicked. Since you didn't actually post your click handlers, it's hard to advise more.
But this is also a bad pattern, functions take arguments for a good reason. Since you have to find your clicked item in the click handler anyway, why not pass it directly which does involve a shared global variable at all?
var handleMouseUp = function(event) {
var story = findClickedThing(event);
if (obj) {
showPopup(story.texture, story.caption);
}
}
Which brings me to this:
var titles = ["a","b","c"];
var captions = ["good","better","best"];
var images = ['imagesphere/assets/1.jpg',
'imagesphere/assets/bp/2.png',
'imagesphere/assets/bp/3.png'
];
When you have 3 arrays, all of the same length, each array describing a different property of an object, you are doing it wrong. What you want, is one array of objects instead.
var stories = [
{
title: "a",
caption: "good",
image: "imagesphere/assets/1.jpg"
}, {
title: "b",
caption: "better",
image: "imagesphere/assets/bp/2.jpg"
}, {
title: "c",
caption: "best",
image: "imagesphere/assets/bp/3.jpg"
},
];
console.log(stories[1].caption); // "better"
Now once you find the clicked object, you can just ask it what it's caption is. And you can pass the whole object to the popup maker. And no field is handled differently or passed around in a different manner, because you are not passing around the fields. You are passsing the entire object.