How to wait until lines are printed iteratively? - javascript

I am building a terminal like personal website and I want to display a welcome banner + message after one another. I have this cool effect where individual lines appear from top to bottom and characters from left to right (See here for yourself).
My problem is that the welcome banner and the welcome message are mixed up with one another. Thus, I want to wait until the banner is printed before printing the message. However something about my code must be wrong... (I tried using await/async) ...
Here you have a small reproducible example of the issue. All lines with the character "a" should be printed before lines with character "b". Can you please point out what the root of the problem is?
banner = ["aaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaa"]
welcomeMsg = ["bbbbbbbbbbbb", "bbbbbbbbbbbb", "bbbbbbbbbbbb", "bbbbbbbbbbbb"]
var before = document.getElementById("before");
setTimeout(async function() {
await loopLines(banner, "", 80);
loopLines(welcomeMsg, "", 80);
}, 100);
async function addLine(text, style, time) {
var t = "";
for (let i = 0; i < text.length; i++) {
if (text.charAt(i) == " " && text.charAt(i + 1) == " ") {
t += " ";
i++;
} else {
t += text.charAt(i);
}
}
setTimeout(function() {
var next = document.createElement("p");
next.innerHTML = t;
next.className = style;
before.parentNode.insertBefore(next, before);
window.scrollTo(0, document.body.offsetHeight);
}, time);
return;
}
async function loopLines(name, style, time) {
for (var i = 0; i < name.length; i++) {
await addLine(name[i], style, i * time);
}
return;
}
p {
display: block;
line-height: 1.3em;
margin: 0;
overflow: hidden;
/* white-space: nowrap; */
margin: 0;
letter-spacing: 0.05em;
animation: typing 0.5s steps(30, end);
/* font-size: calc(2vw + 7px); */
font-size: min(20px, calc(1.5vw + 7px));
}
#keyframes typing {
from {
width: 0;
}
to {
width: 100%;
}
}
<a id="before"></a>

In addLine you don't use await. Instead you call setTimeout, but that doesn't return a pending promise. So the promise returned by addLine resolves immediately without waiting for the timeout to complete.
To change that, make use of a promisified version of setTimeout. I have added its definition at the top of the snippet. Then see where addLine uses it instead of setTimeout:
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
banner = ["aaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaa"]
welcomeMsg = ["bbbbbbbbbbbb", "bbbbbbbbbbbb", "bbbbbbbbbbbb", "bbbbbbbbbbbb"]
var before = document.getElementById("before");
setTimeout(async function() {
await loopLines(banner, "", 80);
loopLines(welcomeMsg, "", 80);
}, 100);
async function addLine(text, style, time) {
var t = "";
for (let i = 0; i < text.length; i++) {
if (text.charAt(i) == " " && text.charAt(i + 1) == " ") {
t += " ";
i++;
} else {
t += text.charAt(i);
}
}
await delay(time); // <---------------
var next = document.createElement("p");
next.innerHTML = t;
next.className = style;
before.parentNode.insertBefore(next, before);
window.scrollTo(0, document.body.offsetHeight);
}
async function loopLines(name, style, time) {
for (var i = 0; i < name.length; i++) {
await addLine(name[i], style, i * time);
}
}
p {
display: block;
line-height: 1.3em;
margin: 0;
overflow: hidden;
/* white-space: nowrap; */
margin: 0;
letter-spacing: 0.05em;
animation: typing 0.5s steps(30, end);
/* font-size: calc(2vw + 7px); */
font-size: min(20px, calc(1.5vw + 7px));
}
#keyframes typing {
from {
width: 0;
}
to {
width: 100%;
}
}
<a id="before"></a>

Related

function that targets DOM to display game results not responding despite calling function and there are no console errors either

I am trying to understand why the function endResult() does not work when either winning or losing a game of hangman.
I have called the function at the bottom of the code and there are no errors in the console.
But when the game finishes (either guessing the word completely within 5 guesses or running out of guesses), there is no action taken from this function.
This is my first intermediate challenge and I still clearly have a lot to learn but any help would be extremely welcome.
Thanks
//global variables.
//counter to display how many tries you have left at guessing correct characters.
var triesLeft = 5;
//dom targets.
var guessCount = document.querySelector("#guesses, p"); //display how many tries you have left in dom target.
var resetButton = document.querySelector(".button"); // reset buton
var displayWord = document.getElementById("puzzle") //dom target to show random word
//arrays
var words = ["hello world", "happy birthday", "you got talent", "china town", "leap frog",
"true lies", "artificial inteligence", "knoledge is power", "monday blues", "autonomous vehicles"];
var wrongGuess = [];
//pick a word randomly.
var randomiseWord = words[Math.floor(Math.random() * words.length)];
//hide all characters within [a-z] and replace with *.
var randomiseWordHide = randomiseWord.replace(/[a-z]/gi, '*');
function displayGame() {
//insert each character of the random word into a span tag hidden as *.
for (var i = 0; i < randomiseWord.length; i++) {
var spanTag = document.createElement("span");
displayWord.appendChild(spanTag);
spanTag.textContent = randomiseWordHide[i];
}
};
function makeAGuess(event) {
//if correct guess, reveal characters,
for (var j = 0; j < randomiseWord.length; j++) {
if (randomiseWord[j] === event.key) {
document.querySelectorAll("span")[j].textContent = event.key;
//else reduce tries left by 1.
} else if (!randomiseWord.includes(event.key)) {
guessCount.textContent = "Guesses Left:" + " " + (triesLeft - wrongGuess.length);
}
}
//if incorrect guess, push to array to keep count. keep this condition out of the loop.
if (!randomiseWord.includes(event.key)) {
wrongGuess.push(event.key);
}
};
function endResult() {
//if word is guessed correctly before running out of guesses.
for (var k=0; k<randomiseWord; k++) {
if (triesLeft >0 && !document.querySelectorAll("span")[j].includes("*")) {
document.querySelector("#guesses, p").textContent = "Well done, you guessed the word with" + triesLeft + " tries left.";
//if all guesses are used and word not complete.
} else if (triesLeft === 0) {
document.querySelector("#guesses, p").textContent = "Nice try, the word was" + '"' + randomiseWord + '".';
}
};
//create a reload button that displays a new random word when clicked.
function reloadScreen() {
reload = location.reload();
}
//listener for keydown
document.addEventListener("keydown", makeAGuess); // can also pass function from here.
//listener for reload button.
resetButton.addEventListener("click", reloadScreen, false);
//call functions.
displayGame();
endResult();
The function endResult() isn't called when the guess was correct or if there are no tries left. You just call the function once at script load. Therefor you should call it in the function makeAGuess():
function makeAGuess(event) {
//if correct guess, reveal characters,
for (var j = 0; j < randomiseWord.length; j++) {
if (randomiseWord[j] === event.key) {
document.querySelectorAll("span")[j].textContent = event.key;
//else reduce tries left by 1.
} else if (!randomiseWord.includes(event.key)) {
guessCount.textContent = "Guesses Left:" + " " + (triesLeft - wrongGuess.length);
}
}
//if incorrect guess, push to array to keep count. keep this condition out of the loop.
if (!randomiseWord.includes(event.key)) {
wrongGuess.push(event.key);
}
endResult();
};
Furthermore there are two issues in endResult():
triesLeft never gets updated an remains 5 -> use wrongGuess.length instead
!document.querySelectorAll("span")[j].includes("*") isn't valid - you have to loop over all span tags and check the condition separately:
function endResult() {
//if word is guessed correctly before running out of guesses.
const letters = document.querySelectorAll("span");
let solved = false;
for (let m = 0; m < letters.length; m++) {
if (letters[m].textContent == "*") {
solved = false;
break;
}
else {
solved = true;
}
}
if (wrongGuess.length < 5 && solved) {
document.querySelector("#guesses, p").textContent = "Well done, you guessed the word with" + (triesLeft - wrongGuess.length) + " tries left.";
//if all guesses are used and word not complete.
} else if (wrongGuess.length >= 5) {
document.querySelector("#guesses, p").textContent = "Nice try, the word was" + '"' + randomiseWord + '".';
}
};
Working example:
//global variables.
//counter to display how many tries you have left at guessing correct characters.
var triesLeft = 5;
//dom targets.
var guessCount = document.querySelector("#guesses, p"); //display how many tries you have left in dom target.
var resetButton = document.querySelector(".button"); // reset buton
var displayWord = document.getElementById("puzzle") //dom target to show random word
//arrays
var words = ["hello world", "happy birthday", "you got talent", "china town", "leap frog",
"true lies", "artificial inteligence", "knoledge is power", "monday blues", "autonomous vehicles"
];
var wrongGuess = [];
//pick a word randomly.
var randomiseWord = words[Math.floor(Math.random() * words.length)];
//hide all characters within [a-z] and replace with *.
var randomiseWordHide = randomiseWord.replace(/[a-z]/gi, '*');
function displayGame() {
//insert each character of the random word into a span tag hidden as *.
for (var i = 0; i < randomiseWord.length; i++) {
var spanTag = document.createElement("span");
displayWord.appendChild(spanTag);
spanTag.textContent = randomiseWordHide[i];
}
};
function makeAGuess(event) {
//if correct guess, reveal characters,
for (var j = 0; j < randomiseWord.length; j++) {
if (randomiseWord[j] === event.key) {
document.querySelectorAll("span")[j].textContent = event.key;
//else reduce tries left by 1.
} else if (!randomiseWord.includes(event.key)) {
guessCount.textContent = "Guesses Left:" + " " + (triesLeft - wrongGuess.length - 1);
}
}
//if incorrect guess, push to array to keep count. keep this condition out of the loop.
if (!randomiseWord.includes(event.key)) {
wrongGuess.push(event.key);
}
endResult();
};
function endResult() {
//if word is guessed correctly before running out of guesses.
const letters = document.querySelectorAll("span");
let solved = false;
for (let m = 0; m < letters.length; m++) {
if (letters[m].textContent == "*") {
solved = false;
break;
} else {
solved = true;
}
}
if (wrongGuess.length < 5 && solved) {
document.querySelector("#guesses, p").textContent = "Well done, you guessed the word with" + (triesLeft - wrongGuess.length) + " tries left.";
//if all guesses are used and word not complete.
} else if (wrongGuess.length >= 5) {
document.querySelector("#guesses, p").textContent = "Nice try, the word was" + '"' + randomiseWord + '".';
}
};
//create a reload button that displays a new random word when clicked.
function reloadScreen() {
reload = location.reload();
}
//listener for keydown
document.addEventListener("keydown", makeAGuess);
//listener for reload button.
resetButton.addEventListener("click", reloadScreen, false);
//call functions.
displayGame();
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 62.5%;
}
body {
background: #2B292E;
color: #fafafa;
font-family: Helvetica, Arial, sans-serif;
font-size: 1.6rem;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
}
span {
border-bottom: 1px solid #534f59;
display: inline-block;
font-size: 2rem;
height: 2.4rem;
line-height: 2.4rem;
margin: 0 .1rem;
text-align: center;
text-transform: uppercase;
width: 2.4rem;
}
p {
font-weight: 300;
margin-bottom: .8rem;
}
.puzzle {
display: flex;
margin-bottom: 4.8rem;
}
.button {
background: #7044a0;
border: none;
border-bottom: 2px solid #603a88;
cursor: pointer;
color: white;
font-size: 1.4rem;
font-weight: 300;
padding: .8rem;
transition: background .3s ease, color .3s ease;
}
.button:hover {
background: #5F3A87;
}
<div>
<div id="puzzle" class="puzzle"></div>
<p id="guesses"></p>
<button id="reset" class="button">Reset</button>
</div>

When i use own sleep() function in javascript my recurency sorting function using quick sorting algorithm doesnt work

Hey I'm a beginner in js. I wanted to do quick sorting function. I have tables with values ​​and I would like to show how they change to show how the function works. Unfortunately the function is almost instantaneous so I did sleep function and added to the sorting function. After that the function didn't work in some cases (some values ​​were unsorted) I think it might have something to do with recursion. Please help how can i do it better? :)
(Other functions like selection sort or bubble sort works properly)
var arr = new Array();
Array.prototype.swap = function (x,y) {
var temp = this[x];
this[x] = this[y];
this[y] = temp;
return this;
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function start_qs(){
for(i=0;i<10;i++){
var value = Math.floor(Math.random() * 100); // random integer from 0 - 100
arr[i] = value;
}
qs(arr, 0, arr.length - 1);
}
function update(effect_id, array){
document.getElementById(effect_id).innerHTML = "";
for(i=0;i<10;i++){
document.getElementById(effect_id).innerHTML += '<div class="label" style="height:'+array[i]+'px;">'+array[i]+'</div>';
}
}
async function qs(array, left, right){
let i = left;
let j = right;
x = array[Math.floor((left+right)/2)];
while(i<=j){
await sleep(50);
while(array[i] < x && i < right){i++;}
while(array[j] > x && j > left){j--;}
if(i <= j){
array.swap(i,j);
i++;
j--;
update("quicksort", arr);
}
}
if(left < j){qs(array, left, j);}
if(i < right){qs(array, i, right);}
}
window.onload = function(){start_qs();}
:root {
--main: #202020;
--sec: #D03737;
}
html{
background: var(--main);
color: var(--sec);
font-size: 28px;
}
body {
margin: 0;
padding: 0;
}
h3{text-align:center;}
.element{margin:auto;width:70%;}
.effect{width:60%;height:200px;margin:auto;}
.label{background: var(--sec); width:7%;margin:0 1.5%;color:black;text-align:center;font-size:0.75rem;}
<script type="text/javascript" src="js/quickSort.js"/></script>
<h2 style="text-align:center;">Javascript algorithms</h2>
<div class="element" id="quicksorting" >
<h3>Quick Sorting
<button style="border-radius:10px;padding:10px 30px;background:var(--main);border-color:var(--sec);color:var(--sec);" onclick="start_qs()">Restart</button></h3>
<div class="content" style="display:flex;">
<div class="effect" id="quicksort" style="display:flex;align-items:flex-end;">
</div>
</div>
</div>
Since you're calling the function recursively, you need to use await in the recursive calls. Otherwise the recursive calls will not execute until the current call finishes, and quicksort requires things all the recursive calls to execute in order.
Also declare x as a local variable, otherwise the recursive calls will overwrite its value.
var arr = new Array();
Array.prototype.swap = function(x, y) {
var temp = this[x];
this[x] = this[y];
this[y] = temp;
return this;
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function start_qs() {
for (i = 0; i < 10; i++) {
var value = Math.floor(Math.random() * 100); // random integer from 0 - 100
arr[i] = value;
}
qs(arr, 0, arr.length - 1);
}
function update(effect_id, array) {
document.getElementById(effect_id).innerHTML = "";
for (let i = 0; i < 10; i++) {
document.getElementById(effect_id).innerHTML += '<div class="label" style="height:' + array[i] + 'px;">' + array[i] + '</div>';
}
}
async function qs(array, left, right) {
let i = left;
let j = right;
let x = array[Math.floor((left + right) / 2)];
while (i <= j) {
await sleep(50);
while (array[i] < x && i < right) {
i++;
}
while (array[j] > x && j > left) {
j--;
}
if (i <= j) {
array.swap(i, j);
i++;
j--;
update("quicksort", arr);
}
}
if (left < j) {
await qs(array, left, j);
}
if (i < right) {
await qs(array, i, right);
}
}
window.onload = function() {
start_qs();
}
:root {
--main: #202020;
--sec: #D03737;
}
html {
background: var(--main);
color: var(--sec);
font-size: 28px;
}
body {
margin: 0;
padding: 0;
}
h3 {
text-align: center;
}
.element {
margin: auto;
width: 70%;
}
.effect {
width: 60%;
height: 200px;
margin: auto;
}
.label {
background: var(--sec);
width: 7%;
margin: 0 1.5%;
color: black;
text-align: center;
font-size: 0.75rem;
}
<script type="text/javascript" src="js/quickSort.js" /></script>
<h2 style="text-align:center;">Javascript algorithms</h2>
<div class="element" id="quicksorting">
<h3>Quick Sorting
<button style="border-radius:10px;padding:10px 30px;background:var(--main);border-color:var(--sec);color:var(--sec);" onclick="start_qs()">Restart</button></h3>
<div class="content" style="display:flex;">
<div class="effect" id="quicksort" style="display:flex;align-items:flex-end;">
</div>
</div>
</div>

Change If Statement to display none if text not number

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);

Add type in animated feature

I wish to create a feature where the letters are typed in between a sentence as it is done in this page .
In the above link there is a sentence inside the banner that says
Create meaningful documents
Create persuasive documents
Create impactful documents
If you notice, the 2nd word is changing while the first and the third word remains the same, can anyone please tell how this animated feature can be achieved
This can be done using javascript. Here is a plugin that i made that types letters using setInterval() function.
Original Demo:
typer = function(e, s, d, t) {
var eI = 0;
var speed = s;
var delay = d;
var eLength = t.length;
var z = 1;
function loop() {
var p = $("<div class='azy-typer-container azy-typer-done'></div>");
var c_t = $("<span class='azy-typer-element'></span>")
var c_b = $("<span class='azy-typer-blinker'>|</span>");
$(".azy-typer-blinker").remove();
p.append(c_t).append(c_b);
$(e).append(p);
interval = setInterval(function() {
c_t.text(t[eI].substring(0, z));
if (z + 1 > t[eI].length) {
clearInterval(interval);
eI = eI + 1;
if (eI + 1 <= t.length) {
z = 0;
setTimeout(loop, d);
}
} else {
z = z + 1;
}
}, s)
}
loop();
}
new typer(".container", 100, 1000, ["Hi there!", "This is a typer demo ", "What do you think about this ?"]);
body {
background: black;
}
span {
font-family: "Courier New";
font-size: 24px;
color: #fff;
font-weight: bold;
}
.azy-typer-blinker {
animation: blink 1s infinite;
}
#keyframes blink {
0% {
color: crimson;
}
50% {
color: transparent;
}
100% {
color: crimson;
}
}
.azy-typer-done {
margin-left: 24px;
}
.azy-typer-done:before {
content: ">>";
color: lightgreen;
font-family: "Courier New";
font-size: 24px;
margin-left: -24px;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container"></div>
You can do some changes to make this code work as you need
typer = function(e, s, d, t) {
var eI = 0;
var speed = s;
var delay = d;
var eLength = t.length;
var z = 1;
function loop() {
var p = $("<div class='azy-typer-container'></div>");
var c_t = $("<span class='azy-typer-element'></span>")
var c_b = $("<span class='azy-typer-blinker'>|</span>");
$(".azy-typer-blinker").remove();
p.append(c_t).append(c_b);
$(e).append(p);
interval = setInterval(function() {
c_t.text(t[eI].substring(0, z));
if (z + 1 > t[eI].length) {
p.addClass("azy-typer-done");
clearInterval(interval);
eI = eI + 1;
if (eI + 1 <= t.length) {
z = 0;
setTimeout(loop, d);
} else {
eI = 0;
z = 0;
setTimeout(loop, d);
}
} else {
z = z + 1;
}
}, s)
}
loop();
}
new typer(".container", 100, 1000, ["Hi there!", "This is a typer demo ", "What do you think about this ?"]);
body {
background: black;
}
span {
font-family: "Courier New";
font-size: 24px;
color: #fff;
font-weight: bold;
}
.azy-typer-blinker {
color: maroon;
}
.azy-typer-container {
display: inline;
}
.azy-typer-done {
display: none;
}
.static {
color: lime;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
<span class="static">Static </span>
</div>
The function takes four arguments
The element to which the text is to be appended
The typing speed
The delay for the next item to appear
The text (should be an array)

jQuery - Image replacement transition [issues in Safari]

Okay I have the following code:-
[SEE JSFIDDLE]
HTML:
<div id="header">
<span class="mobile-menu"></span>
</div>
CSS:
#header {
width: 100%;
background: #000000;
height: 100px;
}
.mobile-menu {
position: absolute;
right: 25px;
top: 20px;
background: url(http://planetbounce.m360.co.uk/wp-content/themes/planetbounce/assets/img/buttons/menu-01.png);
background-repeat: no-repeat;
background-size: 26px !important;
height: 26px;
width: 26px;
display: inline-block;
margin: 7px 0;
-webkit-transition-duration: 0.8s;
-moz-transition-duration: 0.8s;
-o-transition-duration: 0.8s;
transition-duration: 0.8s;
}
.mobile-menu-hover {
background: url(http://planetbounce.m360.co.uk/wp-content/themes/planetbounce/assets/img/mobile-menu-hover.png);
}
jQuery:
var imagesArray = ["http://planetbounce.m360.co.uk/wp-content/themes/planetbounce/assets/img/buttons/menu-01.png",
"http://planetbounce.m360.co.uk/wp-content/themes/planetbounce/assets/img/buttons/menu-02.png",
"http://planetbounce.m360.co.uk/wp-content/themes/planetbounce/assets/img/buttons/menu-03.png",
"http://planetbounce.m360.co.uk/wp-content/themes/planetbounce/assets/img/buttons/menu-04.png",
"http://planetbounce.m360.co.uk/wp-content/themes/planetbounce/assets/img/buttons/menu-05.png",
"http://planetbounce.m360.co.uk/wp-content/themes/planetbounce/assets/img/buttons/menu-06.png",
"http://planetbounce.m360.co.uk/wp-content/themes/planetbounce/assets/img/buttons/menu-07.png"];
function preloadImg(pictureUrls, callback) {
var i, j, loaded = 0;
var imagesArray = [];
for (i = 0, j = pictureUrls.length; i < j; i++) {
imagesArray.push(new Image());
}
for (i = 0, j = pictureUrls.length; i < j; i++) {
(function (img, src) {
img.onload = function () {
if (++loaded == pictureUrls.length && callback) {
callback(imagesArray);
}
};
img.src = src;
}(imagesArray[i], pictureUrls[i]));
}
};
function changeImage(background, imagesArray, index, reverse) {
background.css("background-image", "url('" + imagesArray[index].src + "')").fadeIn(10, function() {
if (reverse) {
index--;
if (index == -1) {
return; // stop the interval
}
} else {
index++;
if (index == imagesArray.length) {
return; // stop the interval
}
}
//Fade in the top element
background.fadeOut(10, function () {
//Set the background of the top element to the new background
background.css("background-image", "url('" + imagesArray[index] + "')");
changeImage(background, imagesArray, index, reverse);
});
});
}
jQuery(function () {
/* Preload Image */
preloadImg(imagesArray, function (imagesArray) {
jQuery(".mobile-menu").css("background-image", "url('" + imagesArray[0].src + "')")
jQuery('.mobile-menu').on('click', {imgs: imagesArray}, function (event) {
var background = jQuery(".mobile-menu");
var bi = background.css('background-image');
var index = 0;
var reverse = false;
if (imagesArray[0].src != bi.replace('url("', '').replace('")', '')) {
index = imagesArray.length - 1;
reverse = true;
}
changeImage(background, event.data.imgs, index, reverse);
});
});
});
The Issue:
This works fine in Firefox and Chrome, it transitions between the 7 different images on click, then does the reverse on the second click (toggling).
The problem is when I try this in Safari, it basically goes through the image replacement process then reverts back to the first image for some reason and I can't figure out why?
Any ideas?
It seems to be because Safari returns the background-image without double quotes, but your replace function checks for url(", so it doesn't replace and reverse never gets true.
Instead of replacing you can check using either indexOf or matching using a RegExp, it would be safer and more straightforward. Either:
if ( bi.indexOf(imagesArray[0].src) == -1) {
or
if (imagesArray[0].src != bi.match(/http.+png/)[0]) {
With indexOf: http://jsfiddle.net/u9ske14r/

Categories