I have working but ugly solution.
Idea is:
Run progress bar before ajax call
Jump to end of progress bar when complete (or fail)
Wait at 90% if ajax call is not finished yet (when finish than jump to end)
There are at least three problems in my solution:
I have to reset progress bar 'width' in 3 places.
I must have public variable (widthProgressBar)
I cannot reuse function 'startProgress' in case I want to have two progress bars at same page.
This is my solution: http://jsfiddle.net/WQXXT/5403/
var widthProgressBarPing = 0;
// handles the click event, sends the query
function getSuccessOutput() {
widthProgressBar = 0;
startProgress("pingTestBar");
$.ajax({
url: '/echo/js/?js=hello%20world!',
complete: function(response) {
widthProgressBar = 99;
},
error: function() {
widthProgressBar = 99;
},
});
return false;
}
function startProgress(barId) {
var elem = document.getElementById(barId);
var id = setInterval(frame, 15);
function frame() {
if (widthProgressBar >= 90 && widthProgressBar < 99) {}
if (widthProgressBar >= 100) {
clearInterval(id);
} else {
widthProgressBar++;
elem.style.width = widthProgressBar + '%';
elem.innerHTML = widthProgressBar * 1 + '%';
}
}
}
.testProgress {
width: 100%;
background-color: #ddd;
}
.testProgressBar {
width: 0%;
height: 30px;
background-color: #4CAF50;
text-align: center;
line-height: 30px;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
test success |
<div class="testProgress">
<div id="pingTestBar" class="testProgressBar"></div>
</div>
I believe this is the right approach, without changing unnecessary variables outside usage scope.
// handles the click event, sends the query
function getSuccessOutput() {
var bar = new Bar("pingTestBar");
$.ajax({
url: '/echo/js/?js=hello%20world!',
complete: function(response) {
bar.finish()
},
error: function() {
bar.finish()
},
});
return false;
}
function Bar(barId) {
var self = this;
self.w = 0;
var elem = document.getElementById(barId);
var id = setInterval(frame, 15);
this.finish = function(){
clearInterval(id);
self.w = 100;
changeElem()
}
function changeElem(){
elem.style.width = self.w + '%';
elem.innerHTML = self.w * 1 + '%';
}
function frame() {
if (self.w >= 90 && self.w < 99) {}
if (self.w >= 100) {
} else {
self.w++;
changeElem()
}
}
}
.testProgress {
width: 100%;
background-color: #ddd;
}
.testProgressBar {
width: 0%;
height: 30px;
background-color: #4CAF50;
text-align: center;
line-height: 30px;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
test success |
<div class="testProgress">
<div id="pingTestBar" class="testProgressBar"></div>
</div>
Here's your code modified.
I eliminated the global var widthProgressBarPing by using the width of the barId element that's always there (var widthProgressBar = elem.style.width.slice(0, -4);).
// handles the click event, sends the query
function getSuccessOutput(barId) {
widthProgressBar = 0;
startProgress(barId);
$.ajax({
url: '/echo/js/?js=hello%20world!',
complete: function(response) {
widthProgressBar = 99;
},
error: function() {
widthProgressBar = 99;
},
});
return false;
}
function startProgress(barId) {
var elem = document.getElementById(barId);
var widthProgressBar = elem.style.width.slice(0, -4);
var id = setInterval(frame, 15);
function frame() {
if (widthProgressBar >= 90 && widthProgressBar < 99) {}
if (widthProgressBar >= 100) {
clearInterval(id);
} else {
widthProgressBar++;
elem.style.width = widthProgressBar + '%';
elem.innerHTML = widthProgressBar * 1 + '%';
}
}
}
.testProgress {
width: 100%;
background-color: #ddd;
}
.testProgressBar {
width: 0%;
height: 30px;
background-color: #4CAF50;
text-align: center;
line-height: 30px;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
test success ||
<div class="testProgress">
<div id="pingTestBar" class="testProgressBar"></div>
</div>
By passing an argument to startProgress(barId) you can use the same function for different bars.
// handles the click event, sends the query
function getSuccessOutput(barId) {
widthProgressBar = 0;
startProgress(barId);
$.ajax({
url: '/echo/js/?js=hello%20world!',
complete: function(response) {
widthProgressBar = 99;
},
error: function() {
widthProgressBar = 99;
},
});
return false;
}
function startProgress(barId) {
var elem = document.getElementById(barId);
var widthProgressBar = elem.style.width.slice(0, -4);
var id = setInterval(frame, 15);
function frame() {
if (widthProgressBar >= 90 && widthProgressBar < 99) {}
if (widthProgressBar >= 100) {
clearInterval(id);
} else {
widthProgressBar++;
elem.style.width = widthProgressBar + '%';
elem.innerHTML = widthProgressBar * 1 + '%';
}
}
}
.testProgress {
width: 100%;
background-color: #ddd;
}
.testProgressBar {
width: 0%;
height: 30px;
background-color: #4CAF50;
text-align: center;
line-height: 30px;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
test success ||
test success2
<div class="testProgress">
<div id="pingTestBar" class="testProgressBar"></div>
</div>
<div class="testProgress">
<div id="pingTestBar2" class="testProgressBar"></div>
</div>
[cut] There are at least three problems in my solution:
I have to reset progress bar 'width' in 3 places
I must have public
variable (widthProgressBar)
I cannot reuse function 'startProgress' in
case I want to have two progress bars at same page.
Simply initialize/reset once when getSuccessOutput() starts
Use the width attribute stored on each bar
Pass the "bar" as arguments, so you can use many bars as you need.
Anyway, you could use .animate() in order to show the progress, so you avoid to keep interval id and the code is more readable.
Please, take a look to following snippet:
function getSuccessOutput() {
//Reset all progress bars
$(".testProgressBar").width(0);
$(".testProgressBar").text("");
//Start requests
doRequest($("#pingTestBar"), 1200);
doRequest($("#pingTestBar2"), 1500);
doRequest($("#pingTestBar3"), 800);
}
function startProgress(bar) {
bar.animate(
{
width:'100%'
},
{
step: function() {
setText(bar);
},
duration: 2000
}
);
}
function complete(bar) {
console.log("Complete " + bar.attr('id'));
bar.finish().animate(
{
width:'100%'
},
{
step: function(){
setText(bar);
}
}
);
}
function setText(bar){
var text = bar.width() / bar.parent().width() * 100;
bar.text(text.toFixed(0));
}
function mockAjax(options) {
var that = {
done: function done(callback) {
if (options.success)
setTimeout(callback, options.timeout, options.response);
return that;
},
error: function error(callback) {
if (!options.success)
setTimeout(callback, options.timeout, options.response);
return that;
}
};
return that;
}
function doRequest(bar, duration){
var mock = {
ajax: function() {
return mockAjax({
success: true,
response: {},
timeout: duration
});
}
};
startProgress(bar);
mock.ajax()
.done(
function (response) {
complete(bar);
}
)
.error(
function (response) {
complete(bar);
}
);
}
.testProgress {
width: 100%;
background-color: #ddd;
}
.testProgressBar {
width: 0%;
height: 30px;
background-color: #4CAF50;
text-align: center;
line-height: 30px;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
test success |
<div class="testProgress">
<div id="pingTestBar" class="testProgressBar"></div>
</div>
<div class="testProgress">
<div id="pingTestBar2" class="testProgressBar"></div>
</div>
<div class="testProgress">
<div id="pingTestBar3" class="testProgressBar"></div>
</div>
I hope it helps you, bye.
Related
I hope you can give me a hand with this. My idea is to show a list of high-scores after the game is finished for a Doodle Jump project (javascript). The high-scores are presented successfully as you will see in my code, but the presentation is poor. Hence, I want to show them in a blank page, if possible using the same html. I will leave my code for you to reproduce the issue and help me. I thought about some document command, but you tell me.
Thanks in advance.
document.addEventListener('DOMContentLoaded', () => {
const grid = document.querySelector('.grid')
const doodler = document.createElement('div')
const unMutedIcon = document.createElement('div')
let doodlerLeftSpace = 50
let startPoint = 150
let doodlerBottomSpace = startPoint
let isGameOver = false
let platformCount = 5
let platforms = []
let upTimerid
let downTimerId
let isJumping = true
let isGoingLeft = false
let isGoingRight = false
let leftTimerId
let rightTimerId
let score = 0
let context
let musicIsPlaying = false
let copyRightMessage = " DoodleJump version by Santiago Hernandez \n all rights reserved \n Copyright © "
const NO_OF_HIGH_SCORES = 10;
const HIGH_SCORES = 'highScores';
function createDoodler() {
grid.appendChild(doodler)
doodler.classList.add('doodler')
doodlerLeftSpace = platforms[0].left
doodler.style.left = doodlerLeftSpace + 'px'
doodler.style.bottom = doodlerBottomSpace + 'px'
}
function control(e) {
if (e.key === "ArrowLeft") {
moveLeft()
} else if (e.key === "ArrowRight") {
moveRight()
} else if (e.key === "ArrowUp") {
moveStraight()
}
}
class Platform {
constructor(newPlatBottom) {
this.bottom = newPlatBottom
this.left = Math.random() * 315
this.visual = document.createElement('div')
const visual = this.visual
visual.classList.add('platform')
visual.style.left = this.left + 'px'
visual.style.bottom = this.bottom + 'px'
grid.appendChild(visual)
}
}
function createPlatforms() {
for (let i = 0; i < platformCount; i++) {
let platGap = 600 / platformCount
let newPlatBottom = 100 + i * platGap
let newPlatform = new Platform(newPlatBottom)
platforms.push(newPlatform)
console.log(platforms)
}
}
function movePlatforms() {
if (doodlerBottomSpace > 200) {
platforms.forEach(platform => {
platform.bottom -= 4
let visual = platform.visual
visual.style.bottom = platform.bottom + 'px'
if (platform.bottom < 10) {
let firstPlatform = platforms[0].visual
firstPlatform.classList.remove('platform')
platforms.shift()
score++
console.log(score)
console.log(platforms)
let newPlatform = new Platform(600)
platforms.push(newPlatform)
}
})
}
}
function jump() {
clearInterval(downTimerId)
isJumping = true
upTimerId = setInterval(function() {
doodlerBottomSpace += 20
doodler.style.bottom = doodlerBottomSpace + 'px'
if (doodlerBottomSpace > startPoint + 200) {
fall()
}
}, 30)
}
function fall() {
clearInterval(upTimerId)
isJumping = false
downTimerId = setInterval(function() {
doodlerBottomSpace -= 5
doodler.style.bottom = doodlerBottomSpace + 'px'
if (doodlerBottomSpace <= 0) {
gameOver()
}
platforms.forEach(platform => {
if ((doodlerBottomSpace >= platform.bottom) &&
(doodlerBottomSpace <= platform.bottom + 15) &&
((doodlerLeftSpace + 60) >= platform.left) &&
(doodlerLeftSpace <= (platform.left + 85)) &&
!isJumping
) {
console.log('landed')
startPoint = doodlerBottomSpace
jump()
}
})
}, 30)
}
function moveLeft() {
if (isGoingRight) {
clearInterval(rightTimerId)
isGoingRight = false
}
isGoingLeft = true
leftTimerId = setInterval(function() {
if (doodlerLeftSpace >= 0) {
doodlerLeftSpace -= 5
doodler.style.left = doodlerLeftSpace + 'px'
} else moveRight()
}, 30)
}
function moveRight() {
if (isGoingLeft) {
clearInterval(leftTimerId)
isGoingLeft = false
}
isGoingRight = true
rightTimerId = setInterval(function() {
if (doodlerLeftSpace <= 340) {
doodlerLeftSpace += 5
doodler.style.left = doodlerLeftSpace + 'px'
} else moveLeft()
}, 30)
}
function moveStraight() {
isGoingRight = false
isGoingLeft = false
clearInterval(rightTimerId)
clearInterval(leftTimerId)
}
function gameOver() {
console.log('GAME OVER')
isGameOver = true
try {
context.pause()
while (grid.firstChild) {
grid.removeChild(grid.firstChild)
}
grid.innerHTML = score
clearInterval(upTimerId)
clearInterval(downTimerId)
clearInterval(leftTimerId)
clearInterval(rightTimerId)
} catch (err) {
console.log('there was an error at gameover')
while (grid.firstChild) {
grid.removeChild(grid.firstChild)
}
grid.innerHTML = score
clearInterval(upTimerId)
clearInterval(downTimerId)
clearInterval(leftTimerId)
clearInterval(rightTimerId)
}
checkHighScore()
}
function saveHighScore(score, highScores) {
const name = prompt('You got a highscore! Enter name:');
const newScore = {
score,
name
};
// 1. Add to list
highScores.push(newScore);
// 2. Sort the list
highScores.sort((a, b) => b.score - a.score);
// 3. Select new list
highScores.splice(NO_OF_HIGH_SCORES);
// 4. Save to local storage
localStorage.setItem(HIGH_SCORES, JSON.stringify(highScores));
};
function checkHighScore() {
const highScores = JSON.parse(localStorage.getItem(HIGH_SCORES)) ? ? [];
const lowestScore = highScores[NO_OF_HIGH_SCORES - 1] ? .score ? ? 0;
if (score > lowestScore) {
saveHighScore(score, highScores); // TODO
showHighScores(); // TODO
}
}
function showHighScores() {
const highScores = JSON.parse(localStorage.getItem(HIGH_SCORES)) ? ? [];
const highScoreList = document.getElementById('highScores');
highScoreList.innerHTML = highScores.map((score) =>
`<li>${score.score} - ${score.name}</li>`
);
}
function start() {
if (!isGameOver) {
createPlatforms()
createDoodler()
setInterval(movePlatforms, 30)
jump()
document.addEventListener('keyup', control)
}
}
document.addEventListener('keypressed', control)
//attach to buttom
start()
//event listener to play music
document.addEventListener('keypress', function(e) {
if (e.keyCode == 32 || e.code == "Space") {
musicIsPlaying = true
context = new Audio("Music_level1.wav");
context.play()
context.loop = true
}
}) //end of event listener
})
.grid {
width: 400px;
height: 600px;
background-color: yellow;
position: relative;
font-size: 200px;
text-align: center;
background-image: url(bluesky_level1.gif);
background-size: contain;
background-repeat: no-repeat;
background-size: 400px 600px;
margin-right: auto;
margin-left: auto;
}
.doodler {
width: 60px;
height: 85px;
position: absolute;
background-image: url(mariobros_level1.png);
background-size: contain;
background-repeat: no-repeat;
background-size: 60px 85px;
filter: brightness(1.1);
mix-blend-mode: multiply;
}
#audio {
display: none
}
.platform {
width: 85px;
height: 15px;
position: absolute;
background-image: url(platform_tramp_level1.png);
background-size: contain;
background-repeat: no-repeat;
background-size: 85px 15px;
}
.volumeIcon {
width: 30px;
height: 30px;
position: absolute;
top: 570px;
background-image: url(volumeIconMuted.png);
background-size: contain;
background-repeat: no-repeat;
background-size: 30px 30px;
}
.unmutedIcon {
width: 30px;
height: 30px;
position: absolute;
top: 570px;
background-image: url(VolumeIcon.png);
background-size: contain;
background-repeat: no-repeat;
background-size: 30px 30px;
}
#highScores {
width: 400px;
height: 300px;
font-size: 30px;
font-family: "Georgia", "Times New Roman";
text-align: center;
position: absolute;
}
<ol id="highScores"></ol>
<div class="grid">
<div class="volumeIcon"></div>
</div>
I included what I think will reproduce the situation. Hope this helps you help me.
Why not just put:
<ol id = "highScores"></ol>
within a <div> and give that a class that has display: none initally? Like this:
<div class="high-scores-container">
<ol id = "highScores"></ol>
</div>
.high-scores-container {
display: none;
height: 100%;
}
Then when you run your showHighScores() function, grab the high-scores-container div and change the display to block and then at the same time, grab the grid div and set that to display: none. That will give you the effect of displaying your high scores on a separate page but you're just doing so with JS/CSS.
I'm trying to pull through a value from the dataLayer to fire a piece of HTML. All pulling through fine, however if the value is 'undefined' rather than an actual number I don't want it to fire.
How can I solve this? Tried everything but it's returning true/false rather than not firing.
$(document).ready(function () {
for (var i = 0, len = dataLayer.length; i < len; i++) {
if (dataLayer[i].event === "productView")
var viewed = dataLayer[i].P2;
}
function isOnScreen(element) {
var curPos = element.offset();
var curTop = curPos.top - $(window).scrollTop();
var screenHeight = $(window).height();
return (curTop > screenHeight) ? false : true;
}
var intervalId = setInterval(function () {
var addtocart = $('#add-to-cart');
if (isOnScreen(addtocart) === true) {
$('.product-image.main-image').before("<div id='social-overlay' style='color: #fff;text-transform: uppercase;font-family: Muli,Arial,Helvetica,sans-serif; font-size: 11px; font-weight: 800;background: #867dae; opacity: 0.8; padding-top: 10px; padding-bottom: 10px; position: absolute;z-index: 1; width: 100%;'>" + viewed + " people viewed item in the last 24 hours</div>")
setTimeout(function () {
$('#social-overlay').fadeOut(1000);
}, 7000);
clearInterval(intervalId);
}
}, 500);
});
Check if the variable 'viewed' is undefined in the setInterval function you have and add the html value using before function only if the viewed is valid.
var intervalId = setInterval(function() {
var addtocart = $('#add-to-cart');
if ( typeof viewed !== 'undefined' && isOnScreen(addtocart) === true) {
$('.product-image.main-image').before("<div id='social-overlay' style='color: #fff;text-transform: uppercase;font-family: Muli,Arial,Helvetica,sans-serif; font-size: 11px; font-weight: 800;background: #867dae; opacity: 0.8; padding-top: 10px; padding-bottom: 10px; position: absolute;z-index: 1; width: 100%;'>" + viewed + " people viewed item in the last 24 hours</div>") ;
setTimeout(function(){
$('#social-overlay').fadeOut(1000);
}, 7000);
clearInterval(intervalId);
}
}, 500);
var api = "https://fcc-weather-api.glitch.me/api/current?";
var lat, lon;
var unit = "C";
var currentTempInCelcius;
$(document).ready(function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
var lat = "lat=" + position.coords.latitude;
var lon = "lon=" + position.coords.longitude;
getWeather(lat, lon);
});
} else {
window.alert("Geolocation is not supported by this browser.");
}
$('#unit').click(function () {
var currentUnit = $('#unit').text();
var newUnit = currentUnit == "C" ? "F" : "C";
$('#unit').text(newUnit);
if (newUnit === "F") {
$('#temp').text(Math.round(($('#temp').text() * 1.8) + 32));
} else {
$('#temp').text(Math.round(($('#temp').text() - 32) / 1.8));
}
});
function getWeather(lat, lon) {
var apiUrl = api + lat + "&" + lon;
$.ajax({
url: apiUrl, success: function (result) {
$('#city').text(result.name + ", ");
$('#country').text(result.sys.country);
$('#temp').text(result.main.temp);
$('#unit').text(unit);
$('#currentWeather').text(result.weather[0].main);
$('#desc').text(result.weather[0].description);
addIcon(result.weather[0].main);
}
});
}
function addIcon(weather) {
var now = new Date;
if (now.getHours() + 1 >= 6 && now.getHours() + 1 <= 18) {
$('#icon').removeClass();
switch (weather) {
case 'Clear':
$('#icon').addClass('wi wi-day-sunny');
break;
}
$('.bg').addClass(weather);
} else {
$('#icon').removeClass();
switch (weather) {
case 'Rain':
$('#icon').addClass('wi wi-night-rain');
break;
}
$('.bg').addClass('night' + weather);
}
}
});
#container {
width: 100vw;
height: 100vh;
margin: auto;
position: absolute;
}
p {
font-size: 55px;
margin: 25px 0;
font-family: 'Roboto',
sans-serif;
}
i {
font-size: 65px;
}
.bg {
width: 100vw;
height: 100vh;
opacity: 0.5;
z-index: -10;
}
.Clear {
background: url(https://images.unsplash.com/photo-1501412804587-2a024e482830?auto=format&fit=crop&w=1050&q=60&ixid=dW5zcGxhc2guY29tOzs7Ozs%3D);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<p><span id="city"></span><span id="country"></span></p>
<p><span id="temp"></span><span id="unit"></span></p>
<p id="currentWeather"></p>
<p id="desc"></p>
<i id="icon"></i>
</div>
<div class="bg"></div>
I am making a local weather app.
I want to make the unit change when the click event is executed.
However, since I added the element, it doesn't work.
I used the .bg tag to add a background to it, so every time the weather changes, the background will also change.
I guess it is because the .bg div covered the #container div. so I tried z-index, but it still doesn't work.
What can I do to make it work?
Thank you :)
Change the position Relative for the container that is masking the click event. Below is the working solution.
var api = "https://fcc-weather-api.glitch.me/api/current?";
var lat, lon;
var unit = "C";
var currentTempInCelcius;
$(document).ready(function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
var lat = "lat=" + position.coords.latitude;
var lon = "lon=" + position.coords.longitude;
getWeather(lat, lon);
});
} else {
window.alert("Geolocation is not supported by this browser.");
}
$('#unit').click(function () {
var currentUnit = $('#unit').text();
var newUnit = currentUnit == "C" ? "F" : "C";
$('#unit').text(newUnit);
if (newUnit === "F") {
$('#temp').text(Math.round(($('#temp').text() * 1.8) + 32));
} else {
$('#temp').text(Math.round(($('#temp').text() - 32) / 1.8));
}
});
function getWeather(lat, lon) {
var apiUrl = api + lat + "&" + lon;
$.ajax({
url: apiUrl, success: function (result) {
$('#city').text(result.name + ", ");
$('#country').text(result.sys.country);
$('#temp').text(result.main.temp);
$('#unit').text(unit);
$('#currentWeather').text(result.weather[0].main);
$('#desc').text(result.weather[0].description);
addIcon(result.weather[0].main);
}
});
}
function addIcon(weather) {
var now = new Date;
if (now.getHours() + 1 >= 6 && now.getHours() + 1 <= 18) {
$('#icon').removeClass();
switch (weather) {
case 'Clear':
$('#icon').addClass('wi wi-day-sunny');
break;
}
$('.bg').addClass(weather);
} else {
$('#icon').removeClass();
switch (weather) {
case 'Rain':
$('#icon').addClass('wi wi-night-rain');
break;
}
$('.bg').addClass('night' + weather);
}
}
});
#container{
width: 20%;
height: 20%;
margin: auto;
}
p {
font-size: 55px;
margin: 25px 0;
font-family: 'Roboto',
sans-serif;}
i {
font-size: 65px; }
.bg {
width: 100vw;
height: 100vh;
opacity: 0.5;
z-index: 1; }
.Clear {
background: url(https://images.unsplash.com/photo-1501412804587-2a024e482830?auto=format&fit=crop&w=1050&q=60&ixid=dW5zcGxhc2guY29tOzs7Ozs%3D) ; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<p><span id="city"></span><span id="country"></span></p>
<p><span id="temp"></span><span id="unit"></span></p>
<p id="currentWeather"></p>
<p id="desc"></p>
<i id="icon"></i>
</div>
<div class="bg"></div>
Hi remove position: absolute from #container and add some text to #unit span/ add some properties to it (as per your requirement).
#unit {
width: 50px;
height: 50px;
display: inline-block;
}
In your situation, you could remove position: absolute from #container and add it to .bg followed with top:0;left:0, check the updated snippet below:
var api = "https://fcc-weather-api.glitch.me/api/current?";
var lat, lon;
var unit = "C";
var currentTempInCelcius;
$(document).ready(function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
var lat = "lat=" + position.coords.latitude;
var lon = "lon=" + position.coords.longitude;
getWeather(lat, lon);
});
} else {
window.alert("Geolocation is not supported by this browser.");
}
$('#unit').click(function () {
var currentUnit = $('#unit').text();
var newUnit = currentUnit == "C" ? "F" : "C";
$('#unit').text(newUnit);
if (newUnit === "F") {
$('#temp').text(Math.round(($('#temp').text() * 1.8) + 32));
} else {
$('#temp').text(Math.round(($('#temp').text() - 32) / 1.8));
}
});
function getWeather(lat, lon) {
var apiUrl = api + lat + "&" + lon;
$.ajax({
url: apiUrl, success: function (result) {
$('#city').text(result.name + ", ");
$('#country').text(result.sys.country);
$('#temp').text(result.main.temp);
$('#unit').text(unit);
$('#currentWeather').text(result.weather[0].main);
$('#desc').text(result.weather[0].description);
addIcon(result.weather[0].main);
}
});
}
function addIcon(weather) {
var now = new Date;
if (now.getHours() + 1 >= 6 && now.getHours() + 1 <= 18) {
$('#icon').removeClass();
switch (weather) {
case 'Clear':
$('#icon').addClass('wi wi-day-sunny');
break;
}
$('.bg').addClass(weather);
} else {
$('#icon').removeClass();
switch (weather) {
case 'Rain':
$('#icon').addClass('wi wi-night-rain');
break;
}
$('.bg').addClass('night' + weather);
}
}
});
#container { width: 100vw; height: 100vh; margin: auto; }
p { font-size: 55px; margin: 25px 0; font-family: 'Roboto', sans-serif;}
i { font-size: 65px; }
.bg { width: 100vw;position: absolute;top:0;left:0; height: 100vh; opacity: 0.5; z-index: -10; }
.Clear { background: url(https://images.unsplash.com/photo-1501412804587-2a024e482830?auto=format&fit=crop&w=1050&q=60&ixid=dW5zcGxhc2guY29tOzs7Ozs%3D) ; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<p><span id="city"></span><span id="country"></span></p>
<p><span id="temp"></span><span id="unit"></span></p>
<p id="currentWeather"></p>
<p id="desc"></p>
<i id="icon"></i>
</div>
<div class="bg"></div>
I've been wanting to create a timer for my website that countsup, and displays alerts at certain intervals. So like, it starts from 0 and counts upwards when the user pushes a button. From there, it will display a a custom alert at certain intervals... (4 minutes for example)... 45 seconds before that interval, I need the number to change to yellow and 10 seconds before that interval, I need it to change to red... then back to the normal color when it passes that interval.
I've got a basic timer code but I am not sure how to do the rest. I am quite new to this. Any help? Thanks so much in advance.
var pad = function(n) { return (''+n).length<4?pad('0'+n):n; };
jQuery.fn.timer = function() {
var t = this, i = 0;
setInterval(function() {
t.text(pad(i++));
}, 1000);
};
$('#timer').timer();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
You could do something like this
var pad = function (n) {
return ('' + n).length < 4 ? pad('0' + n) : n;
};
jQuery.fn.timer = function () {
var t = this,
i = 0;
setInterval(function () {
t.text(pad(i++));
checkTime(i, t);
}, 1000);
};
$('#timer').timer();
checkTime = function (time, t) {
switch (time -1) {
case 10:
t.css('color','red');
break;
case 20:
t.css('color','yellow');
break;
case 30:
t.css('color','green');
break;
case 40:
t.css('color','black');
break;
default:
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
Something like this should work:
Here is a jsFiddle DEMO
jQuery
$.fn.timer = function (complete, warning, danger) {
var $this = $(this);
var total = 0;
$this.text(total);
var intervalComplete = parseInt(complete, 10);
var intervalWarning = parseInt(intervalComplete - warning, 10);
var intervalDanger = parseInt(intervalComplete - danger, 10);
var clock = setInterval(function () {
total += 1;
$this.text(total);
if (intervalWarning === total) {
// set to YELLOW:
$this.addClass('yellow');
}
if (intervalDanger === total) {
// set to RED:
$this.removeClass('yellow').addClass('red');
}
if (intervalComplete === total) {
// reset:
clearInterval(clock);
$this.removeClass();
alert('COMPLETE!');
}
}, 1000);
};
$(function () {
$('#timer').timer(240, 45, 10);
});
CSS
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
An additional point:
You should place some error validation within the function to ensure your counter completion time is greater than both the warning and danger time intervals.
You can try something like this:
JSFiddle
This is a pure JS timer code. Also for popup you can use something like Bootbox.js.
Code
function timer() {
var time = {
sec: 00,
min: 00,
hr: 00
};
var finalLimit = null,
warnLimit = null,
errorLimit = null;
var max = 59;
var interval = null;
function init(_hr, _min, _sec) {
time["hr"] = _hr ? _hr : 0;
time["min"] = _min ? _min : 0;
time["sec"] = _sec ? _sec : 0;
printAll();
}
function setLimit(fLimit, wLimit, eLimit) {
finalLimit = fLimit;
warnLimit = wLimit;
errorLimit = eLimit;
}
function printAll() {
print("sec");
print("min");
print("hr");
}
function update(str) {
time[str] ++;
time[str] = time[str] % 60;
if (time[str] == 0) {
str == "sec" ? update("min") : update("hr");
}
print(str);
}
function print(str) {
var _time = time[str].toString().length == 1 ? "0" + time[str] : time[str];
document.getElementById("lbl" + str).innerHTML = _time;
}
function validateTimer() {
var c = "";
var secs = time.sec + (time.min * 60) + (time.hr * 60 * 60);
console.log(secs, finalLimit)
if (secs >= finalLimit) {
stopTimer();
} else if (secs >= errorLimit) {
c = "error";
} else if (secs >= warnLimit) {
c = "warn";
} else {
c = "";
}
var element = document.getElementsByTagName("span");
console.log(element, c)
document.getElementById("lblsec").className = c;
}
function startTimer() {
init();
if (interval) stopTimer();
interval = setInterval(function() {
update("sec");
validateTimer();
}, 1000);
}
function stopTimer() {
window.clearInterval(interval);
}
function resetInterval() {
stopTimer();
time["sec"] = time["min"] = time["hr"] = 0;
printAll();
startTimer();
}
return {
'start': startTimer,
'stop': stopTimer,
'reset': resetInterval,
'init': init,
'setLimit': setLimit
}
};
var time = new timer();
function initTimer() {
time.init(0, 0, 0);
}
function startTimer() {
time.start();
time.setLimit(10, 5, 8);
}
function endTimer() {
time.stop();
}
function resetTimer() {
time.reset();
}
span {
border: 1px solid gray;
padding: 5px;
border-radius: 4px;
background: #fff;
}
.timer {
padding: 2px;
margin: 10px;
}
.main {
background: #eee;
padding: 5px;
width: 200px;
text-align: center;
}
.btn {
-webkit-border-radius: 6;
-moz-border-radius: 6;
border-radius: 6px;
color: #ffffff;
font-size: 14px;
background: #2980b9;
text-decoration: none;
transition: 0.4s;
}
.btn:hover {
background: #3cb0fd;
text-decoration: none;
transition: 0.4s;
}
.warn {
background: yellow;
}
.error {
background: red;
}
<div class="main">
<div class="timer"> <span id="lblhr">00</span>
: <span id="lblmin">00</span>
: <span id="lblsec">00</span>
</div>
<button class="btn" onclick="startTimer()">Start</button>
<button class="btn" onclick="endTimer()">Stop</button>
<button class="btn" onclick="resetTimer()">Reset</button>
</div>
Hope it helps!
I created a plug-in to display a Metro MessageBar and it works great. I was asked to support callbacks and added some code to the fadeIn functionality for this purpose.
For some reason, the callback shows as a valid function, but doesn't call?
HERE IS THE CONSOLE MESSAGE I AM GETTING:
this.trigger is not a function
...any help is appreciated.
THIS IS HOW TO USE THE PLUG-IN:
this.showSubmitMessage = function () {
var options = {
message: "This is a test.",
messageType: "information"
};
// self.btnSubmit.click IS a valid function!!! Use your own if you want.
nalco.es.rk.globals.messageBarManager.display(options, self.btnSubmit.click);
};
THIS IS THE OFFENDING AREA-OF-CODE IN THE PLUG-IN:
this.fadeIn = function (element, callback) {
element.prependTo(self.container).centerToScrollTop().fadeIn(self.globals.fadeDuration, function() {
if (callback != null)
if ($.isFunction(callback))
setTimeout(function () {
callback();
}, self.globals.callbackDuration);
});
};
THIS IS THE ENTIRE USER-CONTROL PLUG-IN:
Please notice the code for the file-dependency "jquery.Extensions.js" is at the bottom of this posting.
<script src="Scripts/jQuery/Core/jquery-1.6.2.min.js" type="text/javascript"></script>
<script src="Scripts/jQuery/Core/jquery.tmpl.js" type="text/javascript"></script>
<script src="Scripts/jQuery/jquery.Extensions.js" type="text/javascript"></script>
<style type="text/css">
.messageBar { background-color: #DDDDDD; color: #666666; display: none; left: 0; padding: 15px; position: absolute; top: 0; width: 932px; z-index: 1000; }
.messageBar .content { width: 100%; }
.messageBar .content td.image { width: 70px; }
.messageBar .content td.button { width: 60px; }
.messageBar .button { margin-top: 0px; }
.messageBar .content .icon { background-repeat: no-repeat; height: 31px; overflow: hidden; width: 31px; }
.messageBar .content .message { }
.messageBar .content .image { background-repeat: no-repeat; height: 10px; overflow: hidden; width: 70px; }
.messageBar.error { background-color: #FFBABA; color: #D8000C; }
.messageBar.information { background-color: #99CCFF; color: #00529B; }
.messageBar.success { background-color: #DFF2BF; color: #4F8A10; }
.messageBar.warning { background-color: #FEEFB3; color: #9F6000; }
.messageBar.error .content .icon { background-image: url('/_layouts/images/error.png'); }
.messageBar.information .content .icon { background-image: url('/_layouts/images/info.png'); }
.messageBar.success .content .icon { background-image: url('/_layouts/images/success.png'); }
.messageBar.warning .content .icon { background-image: url('/_layouts/images/warning.png'); }
</style>
<script id="template-messageBar" type="text/html">
<div class="messageBar">
<table class="content">
<tbody>
<tr>
<td>
</td>
<td>
</td>
<td>
</td>
<td class="button">
<input type="button" value="Close" class="button metroButton" />
</td>
</tr>
</tbody>
</table>
</div>
</script>
<script id="template-messageBar-icon" type="text/html">
<div class="icon">
</div>
</script>
<script id="template-messageBar-message" type="text/html">
<div class="message">
${Message}
</div>
</script>
<script id="template-messageBar-image" type="text/html">
<div class="image">
</div>
</script>
<script type="text/javascript">
;nalco.es.rk.source.MessageBarManager = (function ($) {
var publicInstances = {};
publicInstances.Controller = Controller;
function Controller(options) {
var self = this;
this.messageTypes = { error: "error", information: "information", normal: null, success: "success", warning: "warning" };
this.globals = {
callbackDuration: 2000,
fadeDuration: 700,
workingImageUrl: "url('/_layouts/images/Nalco.ES.SharePoint.UI/metro-ajax-loader-blue.gif')"
};
this.defaults = {
message: "",
messageType: self.messageTypes.normal,
showIcon: false,
showWorkingImage: false
};
this.container = $('body');
this.templateMessageBarId = '#template-messageBar';
this.templateMessageBarIconId = '#template-messageBar-icon';
this.templateMessageBarMessageId = '#template-messageBar-message';
this.templateMessageBarImageId = '#template-messageBar-image';
this.selectors = { content: '.content', closeButton: '.button', root: '.messageBar' };
this.initialize = function () {
self.display(options);
};
this.display = function (options, callback) {
var empty = {};
var settings = $.extend(empty, self.defaults, $.isPlainObject(options) ? options : empty);
if (settings.messageType != null)
if (settings.messageType.length == 0)
settings.messageType = self.messageTypes.normal;
if (settings.message.length == 0)
return;
var eleMessageBar = $(self.templateMessageBarId).tmpl(empty);
var eleContent = $(self.selectors.content, eleMessageBar);
var eleCellOne = $('td:eq(0)', eleContent);
var eleCellTwo = $('td:eq(1)', eleContent);
var eleCellThree = $('td:eq(2)', eleContent);
var eleMessage = $(self.templateMessageBarMessageId).tmpl({ Message: settings.message });
var btnClose = $(self.selectors.closeButton, eleMessageBar);
if (settings.messageType != self.messageTypes.normal) {
eleMessageBar.addClass(settings.messageType);
if (settings.showIcon) {
var eleIcon = $(self.templateMessageBarIconId).tmpl(empty);
eleCellOne.css('width', '31px');
eleIcon.appendTo(eleCellOne);
}
}
eleMessage.appendTo(eleCellTwo);
btnClose.click(function () {
eleMessageBar.fadeOut(self.globals.fadeDuration, function () {
eleMessageBar.remove();
});
});
if (settings.showWorkingImage) {
var eleImage = $(self.templateMessageBarImageId).tmpl(empty);
eleCellThree.addClass('image');
eleImage.css('background-image', self.globals.workingImageUrl);
eleImage.appendTo(eleCellThree);
}
var elePreviousMessage = $(self.selectors.root, self.container);
if (elePreviousMessage.length > 0) {
btnClose = $(self.selectors.closeButton, elePreviousMessage);
btnClose.click();
setTimeout(function () { self.fadeIn(eleMessageBar, callback); }, self.globals.fadeDuration);
}
else
self.fadeIn(eleMessageBar, callback);
};
this.fadeIn = function (element, callback) {
element.prependTo(self.container).centerToScrollTop().fadeIn(self.globals.fadeDuration, function() {
if (callback != null)
if ($.isFunction(callback))
setTimeout(function () {
callback();
}, self.globals.callbackDuration);
});
};
self.initialize();
};
return publicInstances;
})(jQuery);
function initializeMessageBarManager() {
nalco.es.rk.globals.messageBarManager = new nalco.es.rk.source.MessageBarManager.Controller();
}
$(document).ready(function () {
initializeMessageBarManager();
if (typeof (Sys) != "undefined")
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(initializeMessageBarManager);
});
</script>
THIS IS THE EXTENSIONS DEPENDENCY LISTED IN THE FILES ABOVE:
// **********************
// .centerToScrollTop
// Use -
// Centers an ELEMENT to the window's scrollTop.
//
// Example -
// $('.myElement').centerToScrollTop();
// **********************
(function ($) {
$.fn.extend({
centerToScrollTop: function (options) {
return this.each(function () {
var element = $(this);
var container = $(window);
var scrollTop = container.scrollTop();
var buffer = 30;
var top = scrollTop + buffer;
var left = (container.width() - element.outerWidth()) / 2 + container.scrollLeft();
element.css({ 'position': 'absolute', 'top': top, 'left': left });
return element;
});
}
});
})(jQuery);
This type of error occurs usually if you forgot to include some files like jquery-ui.min.js etc. Check carefully if you add all the necessary references.