how to stop a sound when an animation ends - javascript

I have very little experience in coding in general. But I've somehow managed to get this far with this, and I'm stuck on the very last thing.
This is for a Twitch alert, I'm doing this through 'Stream Elements'
The thing I'm having issues with is stopping the sound once the typing letters have fully appeared, I have no idea how to do this. Is it even possible?
I Forgot to mention, the Typekit links are intentionally broken, as I didn't want to share the link (Since I'm assuming they're all unique and based off your adobe account)
$(document).ready(function() {
var timer, fullText, currentOffset, onComplete, hearbeat = document.getElementById('heartbeat');
heartbeat.play();
function Speak(person, text, callback) {
$("#usernamean-container").html(person);
fullText = text;
currentOffset = 0;
onComplete = callback;
timer = setInterval(onTick, 120
);
}
function onTick() {
currentOffset++;
if (currentOffset == fullText.length) {
complete();
return;
}
var text = fullText.substring(0, currentOffset);
$("#message").html(text);
}
function complete() {
clearInterval(timer);
timer = null;
$("#message").html(fullText);
onComplete()
;
}
$(".box").click(function () {
complete();
});
Speak("{{name}}",
"{{name}} Is now a Witness",
)
//get data from the 🤟 StreamElements 🤟 data injection
const name = '{{name}}';
// vanilla es6 query selection (can use libraries and frameworks too)
const userNameContainer = document.querySelector('#username-container');
// change the inner html to animate it 🤪
userNameContainer.innerHTML = stringToAnimatedHTML(name, animation);
/**
* return an html, with animation
* #param s: the text
* #param anim: the animation to use on the text
* #returns {string}
*/
function stringToAnimatedHTML(s, anim) {
let stringAsArray = s.split('');
stringAsArray = stringAsArray.map((letter) => {
return `<span class="animated-letter ${anim}">${letter}</span>`
});
return stringAsArray.join('');
}
heartbeat.pause();
heartbeat.currentTime = 0;
});
#import url(#import url("https://use.typekit.net/.css");
.awsome-text-container {
font-family: typeka, sans-serif;
font-size: 42px;
font-weight: 400;
}
.image-container {
margin: auto;
display: table;
}
.text-container {
font-family: typeka, sans-serif;
font-size: 26px;
color: rgb(204, 10, 33);
text-align: center;
margin: auto;
text-shadow: rgba(0, 0, 0, 0.5) 1px 1px 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="heart" class="heart">
<audio id="heartbeat" src="https://cdn.discordapp.com/attachments/135995830279733248/733547597305741332/typewriters.mp3" preload="auto"></audio>
<link rel="stylesheet" href="https://use.typekit.net/.css">
<div class="text-container">
<div class="image-container">
<img src="https://media.tenor.com/images/83d6a5ed40a24164dfe1e4e19fad23d9/tenor.gif">
</div>
<div>
<div class="awsome-text-container">
<span id="message"></span>
<br>
</div>
</div>
</div>

Hello and welcome to Stack Overflow!
I have seen messier code and was therefor disappointed ;-). Regarding your question:
Main problem would be that you have a typo in your code and you call the heartbeat.pause(); in the complete method and not at the end of script (as this would be called independently of the completion of the animation).
Typo:
hearbeat = document.getElementById('heartbeat');
Changed method:
function complete() {
clearInterval(timer);
timer = null;
$("#message").html(fullText);
heartbeat.pause();
heartbeat.currentTime = 0;
}
and remove the lines from the bottom of your script.

Related

Display a message once (like a cookie consent) on first visit

I'm building a website and am trying to display a message at the top of the page (inside the header) so it only appears once on every visit/session. An example of this the 'Book an appointment' green bar at the top of this website:
https://www.tiffany.co.uk
My website is here: https://vitrify.tempurl.host/
I've got as far as having a message appear (orange panel at top of page) but currently it appears every time a page is loaded. I just want it to appear once, just like a cookie consent.
I've spent hours looking for a solution but, as I'm not a programmer, I'm struggling. Any help would be much appreciated.
Here's the HTML:
function myFunction() {
var x = document.getElementById("topDIV");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
.topDIV {
color: #000000;
font-weight: 300;
font-size: 15px;
}
.topDIV a:link, .topDIV a:visited {
color: #000000!important;
font-weight: 500;
letter-spacing: -0.3px;
line-height: 1.2 ;
}
span.topDIV {
}
.topDIV a:hover {
border-bottom: 1px solid rgba(0,0,0,0.50) !important;
display: inline-block;
}
.button-x {
position: relative;
float: right;
top: -5px;
background:none;
border:none;
color:rgb(0,0,0) ;
cursor: pointer;
vertical-align: 0px;
}
.button-x:before {
font-family: 'Times';
content: "X";
font-size:30px;
vertical-align:0px;
opacity:0.5;
}
.button-x:hover {
opacity:1!important;
}
<span class = "topDIV">Welcome to <em>Vitrify</em>. Following in the finest traditions of vitreous enamelled jewellery. Find out more.</span><button class = "button-x" onclick="myFunction()"></button>
As mentioned above you need to use localStorage to solve your problem.
Need to know when page is loaded
Get value from the localStorage
Add event to the button (i removed the onclick event from the html for a cleaner solution)
After click set value for localStorage and hide item
If localStorage have value, hide the element
working example
Javascript
document.addEventListener('DOMContentLoaded', function () {
const topDiv = document.querySelector('.topDIV');
const buttonX = document.querySelector('.button-x');
// Get value from localStorage when open the page
const lS = localStorage.getItem('first-visit');
// Add button 'click' event
buttonX.addEventListener('click', () => {
// Set value to the localStorage
localStorage.setItem('first-visit', false);
// hide DOM element
topDiv.style.display = 'none';
});
// This does not check on the first visit to the page
// If localStorage have value, hide DOM element
if (lS) topDiv.style.display = 'none';
});
Html
<span class="topDIV"
>Welcome to <em>Vitrify</em>.Following in the finest traditions of
vitreous enamelled jewellery.
Find out more.
</span>
<button class="button-x"></button>
You can add a flag "showTopMessage:true" in your local storage or session storage based on one time msg to user or every time he visits. respectively.
On Cross/close icon click set the flag "showTopMessage:false".
const showTopBar = "SHOW_TOP_BAR";
const[showTopBar,setShowTopBar] = useState(true);
useEffect(()=>{
const saveState = localstorage.getItems(showTopBar);
if(saveState) setShowTopBar(saveState);
else localstorage.setItem(showTopBar, true);
},[]);
const handleTopBarClose = () => {
setShowTopBar(false);
localstorage.setItem(showTopBar, false);
}
return(
<div>
{
showTopBar && <TopBarComponent onClose={handleTopBarClose}/>
}
</div>
)

JS/CSS Loading spinner finishes before JS executes

Kinda JS/dev newbie here. Having a play around with a loading spinner - this is the example I'm working from. I've currently got a bunch of JS calculations that are performed on a Flask/SQLite backend API. I'll ignore the CSS as it's likely irrelevant.
document.onreadystatechange = function() {
if (document.readyState !== "complete") {
document.querySelector("main").style.visibility = "hidden";
document.querySelector("#loader").style.visibility = "visible";
} else {
document.querySelector("#loader").style.display = "none";
document.querySelector("main").style.visibility = "visible";
}
};
This in the html:
<main role="main" class="container">
<div id="loader" class="spinner-1"></div>
...content here...
</main>
<script type="text/javascript" src="{{ url_for ('static', filename='scripts/main.js') }}"></script>
The issue is that the JS is still running on DOM load. So the spinner disappears and items are still being added to the DOM via JS. They appear after the spinner disappears, which negates the point of having a spinner!
I've tried several of these methods, but they all work the same.
I thought about having the conditional tied to one of the loading items, but that seems a bit clunky and I'd not be able to repeat the code on other pages on the site. Is there a baked in JS method for doing this properly?
EDIT - some of the JS I'm using
async function recipeGet () {
let response = await fetch('/recipeget/' + recipeId)
let data = await response.json();
return data
};
recipeGet();
async function efficiency () {
let mEfficiency = (await recipeGet()).efficiency;
mEfficiency = mEfficiency / 100
return mEfficiency
}
async function insertEff () {
let eff = await efficiency();
let effElement = document.querySelector('#eff');
effElement.innerText = (((Math.round(abv * 100) / 100 )) + "%");
};
insertEff();
I appreciate this may not be the right way to do things, but I'm still relatively new to developing, and it works currently.
ANSWER:
With the suggestion of the answer below, I managed to implement this:
JS
async function insertEff () {
let eff = await efficiency();
let effElement = document.querySelector('#eff');
effElement.innerText = (((Math.round(abv * 100) / 100 )) + "%");
document.querySelector("#loader").style.display = "none";
document.querySelector("#spins").style.visibility = "visible";
};
HTML
<div id="loader" class="spinner-1"></div>
<div class="tab-content" id="spins">
CSS
#spins {
visibility: hidden;
}
Where spins is the ID of the division I want to hide. It is initially hidden, then unhides when the function is executed. I still have to toy around with the HTML as the spinner jigs around a bit on page load, but that's a relatively trivial problem.
I would maybe change how you're receiving the data on your front end. It seems like you're trying to directly add the data from the back end to the front end using some kind of template.
Instead of doing this, try doing a fetch request from the front end after the page is loaded. That way you get the page much faster, and your spinner will be coordinated with the data you receive, meaning it will only disappear once you have all the data.
Here's an example of an ajax/fetch request:
const API_URL = 'https://opentdb.com/api.php?amount=3'
const dataWrapper = document.querySelector('.data-wrapper')
const spinner = document.querySelector('.spinner')
const data = document.querySelector('.data')
const fetchData = async (URL) => {
try {
const res = await fetch(URL)
const json = await res.json()
// populate data with json
data.innerText = JSON.stringify(json, undefined, 2)
spinner.remove() // or just make display: none; - whatever you need
} catch(err) {
console.log(err.message)
}
}
fetchData(API_URL)
.data-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.spinner {
position: absolute;
width: 100px;
height: 100px;
font-size: 100px;
color: blue;
animation: spin 1s linear infinite;
display: flex;
justify-content: center;
align-items: center;
}
#keyframes spin {
to {
transform: rotate(360deg);
}
}
.data {
background: lightgray;
color: #235789;
font-family: 'Cascadia Code', monospace;
word-break: break-all;
white-space: pre-wrap;
width: 100%;
height: 100%;
overflow-y: scroll;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<div class="data-wrapper">
<div class="spinner">
<i class="fas fa-spinner"></i>
</div>
<pre class="data"></pre>
</div>
The point is, by doing an ajax call in this way, the line where the spinner gets removed will only be reached and executed once the data is fully received.
window.onload = function() {
setTimeout(() => {
document.querySelector('#loader').style.opacity = '0';
setTimeout(() => {
document.querySelector('#loader').style.display = 'none';
document.querySelector('main').style.visibility = 'visible';
}, 200);
}, 1000);
}
I use this code to make my preloader smooth and hide after 1 second of window onload. Maybe this code will help you.

Why don't if statments work when repeated in JavaScript?

I am trying to make a grid where the different boxes will blink based off of a binary value defined within my HTML document. I have created a grid in HTML, where the background colour is automatically green and what I'm trying to achieve is that if my value changes to from 0 to 1 for each of the grid items it will then change the colour to red and blink respectively.
I have managed to get the first one working and thought I could just repeat the code with different variables assigned, however this hasn't worked. The weird thing is, if I remove the code for the first box the second box will start working.
Do I need to add some extra code in JS to separate the if statments?
CSS'
.grid-container {
display: grid;
grid-gap: 50px;
grid-template-columns: auto auto auto;
background-color: grey;
padding: 10px;
}
.grid-item {
background-color: green;
border: 1px solid rgba(0, 0, 0, 0.8);
padding: 50px;
font-size: 30px;
text-align: center;
}
HTML
<div class="grid-container">
<div class="grid-item" id = "blink1">A</div>
<div class="grid-item" id = "blink2">B</div>
</div>
<div class = "values">
<div id = "$box1value"> 1 </div>
<div id = "$box2value"> 1 </div>
</div>
JS
var $box1 = document.getElementById("$box1value").innerHTML;
if ($box1 > 0) {
document.getElementById("blink1").style.backgroundColor = '#ff0000';
// blink "on" state
function show() {
if (document.getElementById)
document.getElementById("blink1").style.visibility = "visible";
}
// blink "off" state
function hide() {
if (document.getElementById)
document.getElementById("blink1").style.visibility = "hidden";
}
for (var i = 900; i < 99999999999; i = i + 900) {
setTimeout("hide()", i);
setTimeout("show()", i + 450);
}
} else {
document.getElementById("blink1").style.backgroundColor = '#098700';
}
/////////////////////next box/////////////////////////////
var $box2 = document.getElementById("$box2value").innerHTML;
if ($box2 > 0) {
document.getElementById("blink2").style.backgroundColor = '#ff0000';// blink "on" state
function show() {
if (document.getElementById)
document.getElementById("blink2").style.visibility = "visible";
}
// blink "off" state
function hide() {
if (document.getElementById)
document.getElementById("blink2").style.visibility = "hidden";
}
for (var i = 900; i < 99999999999999999; i = i + 900) {
setTimeout("hide()", i);
setTimeout("show()", i + 450);
}
} else {
document.getElementById("blink2").style.backgroundColor = '#098700';
}
2 different solutions (all JS vs. mostly CSS)
Keeping the core functionality in JS
Leveraging CSS for core functionality
I see what you're trying to achieve here, and I see a couple of different ways to accomplish this. Both of the solutions below allow your code to dynamically loop through any number of box items— no need to write a separate block for each item.
The first example below is modeled more similar to yours, based on
your code but rewritten to work more dynamically. The second solution
further down greatly simplifies things by moving all initialization
scripting into CSS, leaving JS responsible for only boolean switching
if you need to make any real-time state switches.
#1. Keeping the core functionality in JS
This solution modifies your original code to dynamically read the values for however many values there are, and then looping through them. In order to perform the repeated blinking in JS, I would suggest using setInterval. You'll also need to move that outside the rest of the code when using a loop or you'll end up with a conflict between the loop's iterator and the setInterval's and setTimeout's timing. More on that here. You can see the working example below:
function blink(el) {
if (el.style) {
setInterval(function() {
el.style.visibility = "visible";
setTimeout(function() {
el.style.visibility = "hidden";
}, 450);
}, 900);
}
}
const $boxes = document.querySelectorAll('[id^="blink"]');
for (const $box of $boxes) {
var boxId = $box.id.match(/\d+/)[0]; // store the ID #
if (document.getElementById('$box' + boxId + 'value')) {
var boxValue = parseInt(document.getElementById('$box' + boxId + 'value').innerHTML);
if (boxValue) {
$box.style.backgroundColor = '#ff0000';
blink($box);
} else {
$box.style.backgroundColor = '#098700';
}
}
}
.grid-container {
display: grid;
grid-gap: 50px;
grid-template-columns: auto auto auto;
background-color: grey;
padding: 10px;
}
.grid-item {
background-color: #098700;
border: 1px solid rgba(0, 0, 0, 0.8);
padding: 50px;
font-size: 30px;
text-align: center;
}
.values {
display: none;
}
<div class="grid-container">
<div class="grid-item" id="blink1">A</div>
<div class="grid-item" id="blink2">B</div>
<div class="grid-item" id="blink3">C</div>
</div>
<div class="values">
<div id="$box1value">1</div>
<div id="$box2value">0</div>
<div id="$box3value">1</div>
</div>
CodePen: https://codepen.io/brandonmcconnell/pen/ecc954bad5552962574c080631700932
#2. Leveraging CSS for core functionality
This solution moves all of your JS code (color and animation) to the CSS, moving the binary boolean switch 0/1 to data-attributes on the grid-items themselves instead of separate items and then trigger any boolean switches on those containers using JS by targeting them by another attribute such as ID, or as I used in my example below, another data-attribute I called data-blink-id. This is my recommended solution if you're able to move all of this logic into CSS. It'll be much easier to maintain and to manipulate in real-time, as all it requires to change state is a simple boolean switch.
.grid-container {
display: grid;
grid-gap: 50px;
grid-template-columns: auto auto auto;
background-color: grey;
padding: 10px;
}
.grid-item {
background-color: #098700;
border: 1px solid rgba(0, 0, 0, 0.8);
padding: 50px;
font-size: 30px;
text-align: center;
}
.grid-item[data-blink-status="1"] {
background-color: #f00;
animation: blink 900ms linear infinite forwards;
}
#keyframes blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
<div class="grid-container">
<div class="grid-item" data-blink-id="1" data-blink-status="1">A</div>
<div class="grid-item" data-blink-id="2" data-blink-status="0">B</div>
<div class="grid-item" data-blink-id="3" data-blink-status="1">C</div>
</div>
CodePen: https://codepen.io/brandonmcconnell/pen/5b4f3090b3590902b11d50af43361758
To trigger the binary boolean switch on an item (turn ON/OFF), use the below JS command. I've commented this out in the CodePen example linked above. Un-comment this JS line to activate it and switch ON the block with data-blink-id=2
document.querySelector('[data-blink-id="2"]').setAttribute('data-blink-status', 1);
Even though your functions are declared inside if statements, they are still global.
So, you essentially redeclare the show and hide functions, and they stop working.
To make those functions local to the if statement, you'll have to use one of the ES6 block scope declarations, let or const, like this:
const show = function(){ ... }
const hide = function(){ ... }
To do this, you should also replace setTimeout's first argument with a reference to the function (actually, you should always do that):
setTimeout(hide, i)
setTimeout(show, i + 450)
Other improvements you can make:
Avoid that loop that sets timeouts. It's ugly, takes long to execute, and doesn't work forever. Instead, replace setTimeouts with setIntervals.
Remove the if (document.getElementById) part. You can count on it to be defined (it has been around for a loooong time...)
So, you get to:
var $box1 = document.getElementById("$box1value").innerHTML;
if ($box1 > 0) {
document.getElementById("blink1").style.backgroundColor = '#ff0000';// blink "on" state
const show = function () {
document.getElementById("blink1").style.visibility = "visible";
}
// blink "off" state
const hide = function () {
document.getElementById("blink1").style.visibility = "hidden";
}
let flag = false //This is needed to keep track if the element is visible
setInterval(function(){
if(flag = !flag)
hide()
else
show()
}, 450);
} else {
document.getElementById("blink1").style.backgroundColor = '#098700';
}
/////////////////////next box/////////////////////////////
var $box2 = document.getElementById("$box2value").innerHTML;
if ($box2 > 0) {
document.getElementById("blink2").style.backgroundColor = '#ff0000';// blink "on" state
const show = function () {
document.getElementById("blink2").style.visibility = "visible";
}
// blink "off" state
const hide = function () {
document.getElementById("blink2").style.visibility = "hidden";
}
let flag = false //This is needed to keep track if the element is visible
setInterval(function(){
if(flag = !flag)
hide()
else
show()
}, 450);
} else {
document.getElementById("blink2").style.backgroundColor = '#098700';
}

Why does the last character keeps on printing repeatedly?

I have written the following to animate the text in a div, but I cannot find how does the last character gets printed repeatedly.
var textClass = $(".first-text");
var text = textClass.text();
textClass.text("");
for (var i in text) {
$(textClass).animate({
opacity: 0.25
}, 200, function() {
$(textClass).append(text.charAt(i));
});
}
p:not(:first-child) {
display: none;
}
p {
margin: 0 auto;
font-size: 24px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="animate-text">
<p class="first-text">HTML</p><br>
</div>
If I try to the alert the value of i or text.charAt(i), I always get the desired output, but when I try to append the same in a div, I always get the same last letter that is printed repeatedly. I cannot find where I am mistaken. I cannot the find the bug in my logic.
If anyone could enlighten me on my mistake in the above code, I would be glad to hear it.
Here is the link to my fiddle where I tried this code.
Thanks in advance.
You've stumbled into a bit of learning when it comes to closures. When i loops through, and eventually gets run inside the function, it's only looking at the last character, because that's what i was overwritten to before the first animate() actually fires.
You can counteract this by manually creating a closure yourself, wrapping it in a function and passing it in, to preserve the variable at the time of the loop.
For more information on closures, check out: What is a 'Closure'?
var textClass = $(".first-text");
var text = textClass.text();
textClass.text("");
for (var i in text) {
(function (char) {
$(textClass).animate({
opacity: 0.25
}, 200, function() {
$(textClass).append(text.charAt(char));
});
})(i)
}
p:not(:first-child) {
display: none;
}
p {
margin: 0 auto;
font-size: 24px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="animate-text">
<p class="first-text">HTML</p><br>
</div>
Alternatively, you can use new let or const syntax, which defines i for the scope of the block (Which essentially creates a closure around your if block.)
var textClass = $(".first-text");
var text = textClass.text();
textClass.text("");
for (const i in text) {
$(textClass).animate({
opacity: 0.25
}, 200, function() {
$(textClass).append(text.charAt(i));
});
}
p:not(:first-child) {
display: none;
}
p {
margin: 0 auto;
font-size: 24px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="animate-text">
<p class="first-text">HTML</p><br>
</div>
You can either create a closure or use let or const to declare the variable i inside for loop which will preserve the current value of i in each iteration:
var textClass = $(".first-text");
var text = textClass.text();
textClass.text("");
for (const i in text) {
$(textClass).animate({
opacity: 0.25
}, 200, function() {
$(textClass).append(text.charAt(i));
});
}
p:not(:first-child) {
display: none;
}
p {
margin: 0 auto;
font-size: 24px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="animate-text">
<p class="first-text">HTML</p><br>
</div>
Using the let and const instead of var you get a better scoping and do not need to create a closure. Also no need to keep doing $(textClass) - you can cache the object
const $textClass = $(".first-text");
const text = $textClass.text();
$textClass.text("");
for (let i in text) {
$textClass.animate({
opacity: 0.25
}, 200, function() {
$textClass.append(text.charAt(i));
});
}
p:not(:first-child) {
display: none;
}
p {
margin: 0 auto;
font-size: 24px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="animate-text">
<p class="first-text">HTML</p><br>
</div>
It seems to have a variable declaration in your script.
var textClass = $(".first-text");
var text = textClass.text();
textClass.text("");
for (const i in text){
$(textClass).animate({
opacity: 0.25
}, 200, function(){
$(textClass).append(text.charAt(i));
});
}
Please review the following JSFiddle link.
http://jsfiddle.net/tp3juw54/19/

meteor iterate over a set of Sessions to check if the value have changed

I got those Sessions:
Session.set("group_name",false);
Session.set("group_date",false);
Session.set("group_friends",false);
Session.set("group_location",false);
Session.set("group_rules",false);
Session.set("group_desc",false);
Session.set("group_save",false);
I'm using bootstrap progress bar, which only needs width property to be change.
I'm trying to achieve an action similar to Session.get, meaning I want to check if something changed in one of those Sessions so I can increment the width of the progress bar.
I have tried doing something like that:
Meteor.render(function(){
prog = 0 ;
prog = prog;
for( var i in Session.keys){
if(Session.keys.hasOwnProperty(i) && Session.keys[i] != "false"){
prog = prog + 1*15;
}
}
return console.log(prog);
});
my HTML:
<div class="bar" style="width: {{prog}}%;">
That's not working. I'm missing something but I don't know what.
I'm not all that familiar with Meteor.render, but from the docs it returns a reactive fragment which would then need to be appended to the DOM. I'm guessing that's why its not working. That being said, you really don't need to call Meteor.render directly (probably ever). You can do this just with templates and helpers. Here is a complete working example:
test.html
<body>
{{> test}}
</body>
<template name="test">
<div id='progress-wrapper'>
<div id='progress' style='width: {{progress}}%;'></div>
</div>
</template>
test.js
var PROGRESS_VARS = ['group_name', 'group_date', 'group_friends',
'group_location', 'group_rules', 'group_desc', 'group_save'];
Template.test.created = function() {
_.each(PROGRESS_VARS, function(p) {
Session.set(p, false);
});
};
Template.test.helpers({
progress: function() {
var total = 0;
var length = PROGRESS_VARS.length;
_.each(PROGRESS_VARS, function(p) {
if (Session.get(p)) {
total += 1;
}
});
return Math.ceil(100 * total / length);
}
});
test.css
#progress-wrapper {
border: 1px solid #000;
margin-top: 50px;
width: 50%;
}
#progress {
background-color: #008000;
height: 50px;
}

Categories

Resources