I am trying to create something like a Grid-Image-Box-Slider. Now what I am trying to achieve is that after a period of time (e.g 5 seconds) one of the images will be changed randomly. So, my script follows:
var currentImages = [1, 2];
(function imgCarousel() {
var min = 1;
var max = 6;
currentImgSlot = pickImageSlot();
var pickedImage = pickImage();
setTimeout(function () {
console.log("Image Slot: " + currentImgSlot + "<br> Image: " + pickedImage);
//var bgImgElem = document.getElementsByClassName('bg1');
var sheet = new CSSStyleSheet();
sheet.replaceSync('.bg' + currentImgSlot + ' {background-image: url("assets/img/' + pickedImage + '.jpg") !important}');
document.adoptedStyleSheets = [sheet];
return imgCarousel();
}, 5000)
})()
function pickImageSlot() {
var min = 1;
var max = 2;
var generatedImgSlot = generateRandomNumber(max, min);
if (generatedImgSlot == currentImgSlot) {
return pickImageSlot();
}
return generatedImgSlot;
}
function pickImage() {
var min = 1;
var max = 6;
var generatedImg = generateRandomNumber(max, min);
if (currentImages[currentImgSlot] == generatedImg) {
return pickImage();
}
currentImages[currentImgSlot] = generatedImg;
return generatedImg;
}
function generateRandomNumber(max, min) {
return Math.round(Math.random() * (max - min) + min)
}
So, here you can see that inside the imgCarousel() function I am using the setTimeout to change the background-image randomly after 5 seconds and then calling the same function again recursively. So, according to this code after each five seconds only one image should be changed. But, in reality, sometimes both of the images get changed at the same time. I don't know what is causing this issue.
Any help would be much appreciated. For your convenience I am sharing my code repo here:
Git Repo
Live Demo
It's a bit difficult to notice, but if you pay attention, in your live demo you'll actually see that each time they both change, one returns to the default. This is because you're actually just overriding the adoptedStyleSheets property with a new array consisting only of the latest override, so your other image will simultaneously return to the primary style sheet's image (the default).
There is no problem with the setTimeout, the issue is just that you need to be able to support both images being different from the default, instead of exactly one. You already keep both images in currentImages, so each time the timeout runs you can iterate over them and set each one's image in the new adopted style sheet.
Naively, something like this might work:
setTimeout(function () {
console.log("Image Slot: " + currentImgSlot + "<br> Image: " + pickedImage);
//var bgImgElem = document.getElementsByClassName('bg1');
var sheet = new CSSStyleSheet();
for(var i = 1; i < 2; i++) {
sheet.replaceSync('.bg' + i + ' {background-image: url("assets/img/' + currentImages[i]+ '.jpg") !important}');
}
document.adoptedStyleSheets = [sheet];
return imgCarousel();
}, 5000)
Your currentImages seems to be used with a random number between 1 and 2, but arrays are 0-based, so I'm not sure what your intended usage is there, but this should get you on the right track.
so I was given the task to make a unique code by adding numbers after the code.
and I have tried and succeeded but there is one thing that blocks what if the number has reached its limit? 9999 value
how to reset it to 00001. Lift digit increased by 1
here's my snippet code
function getNewCode(value, callback){
let newCode = _.upperCase(value) + "-";
let lastCode = newCode + "0001"
Transaction.findOne({tr_number: new RegExp(newCode, 'i')}, (err, doc) => {
if(err) callback(err)
if (!_.isNil(doc)){
let arr = doc.tr_number.split("-");
// in this part, i want got some conditional to set a new value
//when it got max length = 9999 for an example
let inc = parseInt(arr[1]) + 1;
lastCode = newCode + ("0000"+inc).slice(-4);
console.log('lastCode', ciduk, lastCode);
return callback(lastCode);
}else{
return callback(lastCode);
}
}).sort({tr_number: -1})
};
sorry for my bad language :) grats.
You can get number size by converting it toString() and get it length.
function getNext(prevStr) {
let padSize = prevStr.length;
let next = parseInt(prevStr, 10) + 1;
if (next >= 10 ** padSize) {
padSize++;
next = 1;
}
return next.toString().padStart(padSize, '0');
}
console.log(getNext('0099')); // '0100'
console.log(getNext('9999')); // '00001'
For our digital signage system, I'd like to show how long until the next bus departs. I've built the array that holds all the times and successfully (maybe not elegantly or efficiently) gotten it to change all that to show how much time is remaining (positive or negative) until each listed departure.
I need a nudge in the right direction as to how to determine which bus is next based on the current time. If there is a bus in 7 minutes, I only need to display that one, not the next one that leaves in 20 minutes.
I was thinking perhaps a for loop that looks at the array of remaining times and stops the first time it gets to a positive value. I'm concerned that may cause issues that I'm not considering.
Any assistance would be greatly appreciated.
UPDATE: Unfortunately, all the solutions provided were throwing errors on our signage system. I suspect it is running some limited version of Javascript, but thats beyond me. However, the different solutions were extremely helpful just in getting me to think of another approach. I think I've finally come on one, as this seems to be working. I'm going to let it run over the holiday and check it on Monday. Thanks again!
var shuttleOrange = ["09:01", "09:37", "10:03", "10:29", "10:55", "11:21", "11:47", "12:13", "12:39", "13:05", "13:31", "13:57", "14:23", "14:49", "15:25", "15:51", "16:17", "16:57", "17:37", "18:17"];
var hFirst = shuttleOrange[0].slice(0,2);
var mFirst = shuttleOrange[0].slice(3,5);
var hLast = shuttleOrange[shuttleOrange.length-1].slice(0,2);
var mLast = shuttleOrange[shuttleOrange.length-1].slice(3,5);
var theTime = new Date();
var runFirst = new Date();
var runLast = new Date();
runFirst.setHours(hFirst,mFirst,0);
runLast.setHours(hLast,mLast,0);
if ((runFirst - theTime) >= (30*60*1000)) {
return "The first Orange Shuttle will depart PCN at " + shuttleOrange[0] + "."
} else if (theTime >= runLast) {
return "Orange Shuttle Service has ended for the day."
} else {
for(var i=0, l=shuttleOrange.length; i<l; i++)
{
var h = shuttleOrange[i].slice(0,2);
var m = shuttleOrange[i].slice(3,5);
var departPCN = new Date();
departPCN.setHours(h,m,0);
shuttleOrange[i] = departPCN;
}
for(var i=shuttleOrange.length-1; i--;)
{
//var theTime = new Date();
if (shuttleOrange[i] < theTime) shuttleOrange.splice(i,1)
}
var timeRem = Math.floor((shuttleOrange[0] - theTime)/1000/60);
if (timeRem >= 2) {
return "Departing in " + timeRem + " minutes."
} else if (timeRem > 0 && timeRem < 2) {
return "Departing in " + timeRem + " minute."
} else {
return "Departing now."
}
}
You only need to search once to find the index of the next scheduled time. Then as each time elapses, increment the index to get the next time. Once you're at the end of the array, start again.
A sample is below, most code is setup and helpers. It creates a dummy schedule for every two minutes from 5 minutes ago, then updates the message. Of course you can get a lot more sophisticated, e.g. show a warning when it's in the last few minutes, etc. But this shows the general idea.
window.addEventListener('DOMContentLoaded', function() {
// Return time formatted as HH:mm
function getHHmm(d) {
return `${('0'+d.getHours()).slice(-2)}:${('0'+d.getMinutes()).slice(-2)}`;
}
var sched = ["09:01", "09:37", "10:03", "10:29", "10:55", "11:21", "11:47",
"12:13", "12:39", "13:05", "13:31", "13:57", "14:23", "14:49",
"15:25", "15:51", "16:17", "16:57", "17:37", "18:17","21:09"];
var msg = '';
var msgEl = document.getElementById('alertInfo');
var time = getHHmm(new Date());
var index = 0;
// Set index to next scheduled time, stop if reach end of schedule
while (time.localeCompare(sched[index]) > 0 && index < sched.length) {
++index;
}
function showNextBus(){
var time = getHHmm(new Date());
var schedTime;
// If run out of times, next scheduled time must be the first one tomorrow
if (index == sched.length && time.localeCompare(sched[index - 1]) > 0) {
msg = `Current time: ${time} - Next bus: ${sched[0]} tomorrow`;
// Otherwise, show next scheduled time today
} else {
// Fix index if rolled over a day
index = index % sched.length;
schedTime = sched[index];
msg = `Current time: ${time} - Next bus: ${schedTime}`;
if (schedTime == time) msg += ' DEPARTING!!';
// Increment index if gone past this scheduled time
index += time.localeCompare(schedTime) > 0? 1 : 0;
}
msgEl.textContent = msg;
// Update message each second
// The could be smarter, using setInterval to schedule running at say 95%
// of the time to the next sched time, but never more than twice a second
setInterval(showNextBus, 1000);
}
showNextBus();
}, false);
<div id="alertInfo"></div>
Edit
You're right, I didn't allow for the case where the current time is after all the scheduled times on the first running. Fixed. I also changed all the string comparisons to use localeCompare, which I think is more robust. Hopefully the comments are sufficient.
I have used filter for all shuttle left after the right time and calculated how much time left for the first one.
var shuttleOrange = ["09:01", "09:37", "10:03", "10:29", "10:55", "11:21", "11:47", "12:13", "12:39", "13:05", "13:31", "13:57", "14:23", "14:49", "15:25", "15:51", "16:17", "16:57", "17:37", "18:17"];
var d = new Date();
var h = d.getHours();
var m = d.getMinutes();
var remainShuttle = shuttleOrange.filter(bus => bus.substring(0,2) > h || (bus.substring(0,2) == h && bus.substring(3,5) > m));
var leftMinutes = (parseInt(remainShuttle[0].substring(0,2))*60 + parseInt(remainShuttle[0].substring(3,5)) - (parseInt(h) *60 + parseInt(m)));
console.log(parseInt(leftMinutes / 60) + " hours and " + leftMinutes % 60 +" minutes left for next shuttle");
I have created a function in javascript to check if the time is valid or not, i.e if the new time (has start and end time) is in between a fixed time (has start and end time), it is valid, otherwise invalid.
Working JSFiddle
My code is as given below
Here it is giving valid when i give invalid times
var fixedTime = {start : '2014-11-13T09:00:00', end : '2014-11-13T13:00:00'};
var newTime = {start : '2014-11-13T06:30:00', end : '2014-11-13T08:30:00'};
if(checkDates(fixedTime, newTime))
{
window.alert("Valid");
}
else
{
window.alert("Invalid");
}
function checkDates(fixedTime, newTime)
{
var returnBoolean = true;
if(((new Date(newTime.start).getTime()) <= (new Date(fixedTime.start).getTime()) && (new Date(newTime.start).getTime()) >= (new Date(fixedTime.end).getTime())) || ((new Date(newTime.end).getTime()) <= (new Date(fixedTime.start).getTime()) && (new Date(newTime.end).getTime()) >= (new Date(fixedTime.end).getTime())))
{
returnBoolean = false;
}
return returnBoolean;
}
can anyone please tell me some solutions for this
No need for such enormous complexity. You only need to make two comparisons:
var fixedTime = {
start: new Date('2014-11-13T09:00:00').getTime(),
end: new Date('2014-11-13T13:00:00').getTime()
};
var newTime = {
start: new Date('2014-11-13T06:30:00').getTime(),
end: new Date('2014-11-13T08:30:00').getTime()
};
if (checkDates(fixedTime, newTime)) {
alert("Valid");
} else {
alert("Invalid");
}
function checkDates(fixedTime, newTime) {
return newTime.start > fixedTime.start && newTime.end < fixedTime.end;
}
Fiddle
I have a page that is using jQuery to load an XML file, which I'm then outputting the contents of to the page.
Recently I added a sorting function to the output which is causing a 1+ or 2+ minute hang on Safari on an iPod Touch (depending upon how many fields I sort by) and a less than 1 minute hang on an iPad. The same sort returns within a few seconds on Firefox 4.0.1.
I'm afraid it's just a limitation of the iOS, but before I removed the sort, perhaps there's an optimization that could be made.
Before the filter there's 357 items in the XML. After the filter there's 199 items that are sorted through.
var videoGames = $($.parseXML(videoGameXml)).find("game");
videoGames = videoGames.filter(function (a) {
return ($(this).attr('addOn') != "true" && $(this).find('own').text() == "yes");
});
videoGames.sort(function (a, b) {
var firstTitle = $(a).find('title').text().toLowerCase();
var secondTitle = $(b).find('title').text().toLowerCase();
var firstSystem = ($(a).find("console").text() + " " + $(a).find("version").text()).toLowerCase();
var secondSystem = ($(b).find("console").text() + " " + $(b).find("version").text()).toLowerCase();
if (firstSystem != secondSystem) {
if (firstSystem > secondSystem) {
return 1;
} else {
return -1;
}
} else {
if (firstTitle > secondTitle) {
return 1;
} else if (secondTitle < firstTitle) {
return -1;
}
}
return 0;
});
videoGames.each(function () {
// runs quickly, so removed
});
Note that if I remove the system check as an initial 'optimization' that cuts the time about in half on the iPod Touch, but still results in the 1+ minute hang mentioned above.
So, is it an iOS device limitation, or can I optimize my sort?
Every time you do $(a) it will perform a very complex set of operations, so you better cache it. Also, you don't need the Title if System is different. This version should speed it up a bit:
videoGames.sort(function (a, b) {
var first = $(a);
var second = $(b);
var firstSystem = (first.find("console").text() + " " + first.find("version").text()).toLowerCase();
var secondSystem = (second.find("console").text() + " " + second.find("version").text()).toLowerCase();
if (firstSystem != secondSystem) {
if (firstSystem > secondSystem) {
return 1;
} else {
return -1;
}
} else {
var firstTitle = first.find('title').text().toLowerCase();
var secondTitle = second.find('title').text().toLowerCase();
if (firstTitle > secondTitle) {
return 1;
} else if (secondTitle < firstTitle) {
return -1;
}
}
return 0;
});
You could also cache the values in the object
Then, instead of:
var firstSystem = (first.find("console").text() + " " + first.find("version").text()).toLowerCase();
Do:
var firstSystem = first.data('system');
if (!firstSystem) {
firstSystem = (first.find("console").text() + " " + first.find("version").text()).toLowerCase();
first.data('system') = firstSystem;
}
You should move any selectors calls like this:
var firstTitle = $(a).find('title').text().toLowerCase();
out from the comparator function. The comparator function is supposed to be lightweight.
Either use children(), next() and the like or
scan you set once and create an array of keys upfront and then sort it using those keys.
The comparator function will be called 2n * ln(n) times (depends on algorithm used) where n is a number of elements in a set. So your code does the same expensive calculations twice at least.