MultipleDatePicker - How to show specific range of years in dropdown? - javascript

I have started learning Multipledatepicker and I am making it customize. I have a scenario in which I am taking the calendar to the last date selected for any year/month. Now it works good but now I need to show years in the dropdown from 1960-2028.
But the official documentation says 'When you select a year it'll re-render the select to always have the same range of the selected year'. I don't want this to pick years around the selected year.
<multiple-date-picker change-year-past="5" change-year-future="10"/>
How can I do this?
Js
getYearsForSelect = function () {
var now = moment(),
changeYearPast = Math.max(0, parseInt(scope.changeYearPast, 10) || 0),
changeYearFuture = Math.max(0, parseInt(scope.changeYearFuture, 10) || 0),
min = moment(scope.month).subtract(changeYearPast, 'year'),
max = moment(scope.month).add(changeYearFuture, 'year'),
result = [];
max.add(1, 'year');
for (var m = moment(min); max.isAfter(m, 'YEAR'); m.add(1, 'year')) {
if ((!scope.disallowBackPastMonths || (m.isAfter(now, 'year') || m.isSame(now, 'year'))) && (!scope.disallowGoFuturMonths || (m.isBefore(now, 'year') || m.isSame(now, 'year')))) {
result.push(m.format('YYYY'));
}
}
return result;
};

I came up with this :)
getYearsForSelect = function () {
// var now = moment(),
// changeYearPast = Math.max(0, parseInt(scope.changeYearPast, 10) || 0),
// changeYearFuture = Math.max(0, parseInt(scope.changeYearFuture, 10) || 0),
// min = moment(scope.month).subtract(changeYearPast, 'year'),
// max = moment(scope.month).add(changeYearFuture, 'year'),
var result = [];
// max.add(1, 'year');
for (var m = 1960; m<=2028 ; m++) {
// if ((!scope.disallowBackPastMonths || (m.isAfter(now, 'year') || m.isSame(now, 'year'))) && (!scope.disallowGoFuturMonths || (m.isBefore(now, 'year') || m.isSame(now, 'year')))) {
result.push(m);
// }
}
return result;
}

Related

How do i call a javascript function to execute after another script ends

I am trying to call function sumWH after the completion of the function sumMon1. Both functions get the text from labels, sum up their values, and update a counter label. The code that I have attempted to use to call sumHW after sumMon1 is below and does not work.
$.when(sumMon1()).done(function () {
sumWH();
});
the sum functions look like this:
<script>
$.when(sumMon1()).done(function () {
sumWH();
});
function sumWH() {
alert(event.target);
//Get Friday AM Out Value
var a = parseInt($('[id$="lblWeek1FridayTotalHrs"]').val(), 10) || 0;
//Get Friday AM IN Value
var b = parseInt($('[id$="lblWeek2FridayTotalHrs"]').val(), 10) || 0;
//Get Friday PM Out Value
var c = parseInt($('[id$="lblWeek1SaturdayTotalHrs"]').val(), 10) || 0;
//Get Friday AM IN VALUE
var d = parseInt($('[id$="lblWeek2SaturdayTotalHrs"]').val(), 10) || 0;
//Get Friday AM Out Value
var e = parseInt($('[id$="lblWeek1SundayTotalHrs"]').val(), 10) || 0;
//Get Friday AM IN Value
var f = parseInt($('[id$="lblWeek2SundayTotalHrs"]').val(), 10) || 0;
//Get Friday PM Out Value
var g = parseFloat($('[id$="lblWeek1MondayTotalHrs"]').val(), 10);
//Get Friday AM IN VALUE
var h = parseInt($('[id$="lblWeek2MondayTotalHrs"]').val(), 10) || 0;
//Get Friday AM Out Value
var i = parseInt($('[id$="lblWeek1TuesdayTotalHrs"]').val(), 10) || 0;
//Get Friday AM IN Value
var j = parseInt($('[id$="lblWeek2TuesdayTotalHrs"]').val(), 10) || 0;
//Get Friday PM Out Value
var k = parseInt($('[id$="lblWeek2WednesdayTotalHrs"]').val(), 10) || 0;
//Get Friday AM IN VALUE
var l = parseInt($('[id$="lblWeek1WednesdayTotalHrs"]').val(), 10) || 0;
//Get Friday AM Out Value
var m = parseInt($('[id$="lblWeek2ThursdayTotalHrs"]').val(), 10) || 0;
//Get Friday AM IN Value
var n = parseInt($('[id$="lblWeek1ThursdayTotalHrs"]').val(), 10) || 0;
var result = a + b + c + d + e + f + g + h + i + j + k + l + m + n;
if (result > 0 && result < 81 && !isNaN(result)) {
$('[id$="txtTotalHours"]').html(result);
} else if (result == 0) {
$('[id$="txtTotalHours"]').html(0);
} else if (isNaN(result)) {
$('[id$="txtTotalHours"]').html(result);
}
}
</script>
<script>
$(document).ready(function () {
sumMon1();
$('[id$="txtWeek1MondayPM_OUT"], [id$="txtWeek1MondayAM_OUT"]').on("blur", function () {
sumMon1();
});
});
function sumMon1() {
//Get Monday AM Out Value
var Out2Dec = $('[id$="txtWeek1MondayAM_OUT"]').val();
//split dec and whole AM OUT
var OutAmDec = Out2Dec % 1;
var OutAMWhole = Math.floor(Out2Dec);
if (OutAMWhole < 12 && OutAMWhole != 0 && !isNaN(OutAMWhole)) {
OutAMWhole += 12;
}
//Get Monday AM IN Value
var In2Dec = $('[id$="txtWeek1MondayAM_IN"]').val();
//split dec and whole AM IN
var InAmDec = In2Dec % 1;
var InAmWhole = Math.floor(In2Dec);
//Get Monday PM Out Value
var Out1Dec = $('[id$="txtWeek1MondayPM_OUT"]').val();
//split dec and whole PM OUT
var OutPmDec = Out1Dec % 1;
var OutPMWhole = Math.floor(Out1Dec);
if (OutAMWhole < 12 && OutAMWhole != 0 && !isNaN(OutAMWhole)) {
OutPMWhole += 12;
}
//Get Monday AM IN VALUE
var In1Dec = $('[id$="txtWeek1MondayPM_IN"]').val();
//split dec and whole PM IN
var InPmDec = In1Dec % 1;
var InPMWhole = Math.floor(In1Dec);
//calculate times
var InAmVal = (InAmWhole * 60) + (InAmDec * 100);
var OutAmVal = (OutAMWhole * 60) + (OutAmDec * 100);
var InPmVal = (InPMWhole * 60) + (InPmDec * 100);
var OutPmVal = (OutPMWhole * 60) + (OutPmDec * 100);
var Difference = (OutAmVal - InAmVal) + (OutPmVal - InPmVal);
var result = Difference / 60;
//display result
if (result > 0 && !isNaN(result)) {
$('[id$="lblWeek1MondayTotalHrs"]').html(result.toFixed(2));
} else {
var value2 = (result.toFixed(2) * -1);
$('[id$="lblWeek1MondayTotalHrs"]').html(value2);
}
}
</script>
The sum functions are located in separate script tags. sumMon1 is set to go on blur from a series of textboxes.
Is this there a way to make this function work or is there a better way to accomplish this?
jQuery.when is for async functions.
async is something like setInterval or jQuery.ajax.
And except async stuff, JavaScript (Or almost any other languages as well) run codes from top to the bottom sequentially.
Your code is not using asynchronous things. so simply do
sumMon();
sumWH();

Consecutive business days in Javascript (no weekends)

I need to do a 3 consecutive business day check against an array of dates in javascript. I have it working with any 3 days but I can't figure out for the life of me how I can make this work with the weekend breaking up the consecutive days.
NOTE - This requires moment() library (https://momentjs.com)
My code that works for 3 actual consecutive days:
var allDates = ["2017-03-07", "2017-03-09", "2017-03-10", "2017-03-13", "2017-03-15"];
var diff = 86400000;
var consecutive = 0;
allDates.sort(function(a,b){
return new Date(a) - new Date(b);
});
for (i = 2; i < allDates.length; i++) {
var d = moment(allDates[i], "YYYY-MM-DD").format('x');
var d1 = moment(allDates[i-1], "YYYY-MM-DD").format('x');
var d2 = moment(allDates[i-2], "YYYY-MM-DD").format('x');
if (d1 - d2 == diff && d - d2 == diff * 2) {
consecutive = 1;
break;
}
}
As you can see by the calendar above, I would like March 9th, 10th and 13th to act as 3 consecutive business days. Anyone have any feedback that can guide me onto a right path?
Thanks in advance
You can use the javascript Date object to figure out which days are weekends.
Here is the documentation
And a quick example:
var d1 = new Date("2017-03-07");
var d2 = new Date("2017-03-08");
d.getDay() // this will return 1, which corresponds with Monday. 2 is Tuesday, 3 is Wednesday, etc.
So a small function to tell if 2 dates are consecutive, even if separated by a weekend, could be:
var millisecondsInDay = 86400000;
function datesAreConsecutiveBusinessDays(date1, date2){
// If date1 is a Friday and date2 is a Monday
if (date1.getDay() === 5 && date2.getDay() === 1){
// And the dates are 2 days apart
date2.valeOf() - date1.valueOf() === millisecondsInDay * 2
return true;
} else if (date2.valeOf() - date1.valueOf() === millisecondsInDay){
return true;
} else {
return false;
}
}
So with this method, you go through your list of dates and call it on every two that are next to eachother.
var consecutive = 0;
var allDates = ["2017-03-07", "2017-03-09", "2017-03-10", "2017-03-13", "2017-03-15"];
for (var i = 0; i < allDates.length - 1; i++){
if (datesAreConsecutiveBusinessDays(new Date(allDates[i]), new Date(allDates[i+1])){
consecutive++;
}
// If you want to start over if you hit a nonconsecutive date, add this else:
else {
consecutive = 0; // this will start the counter over
}
}
You might need to tweak the solution a bit depending on how consecutive is calculated, but this should be enough to get you started.
This can be solved by writing a function which determines if any 2 momentjs instances are either 1 day different, or if one is friday and the other is monday (but must only be 3 days apart). Simply, this does it:
function isConsecutive(a,b){
return b.diff(a,"days") == 1
|| (a.weekday() == 5 && b.weekday() == 1 && b.diff(a,"days") == 3);
}
You can then take your array of dates, turn them all to momentJS instances, order them and iterate through calling the above method for each pair. Keep a running total of the count:
function countConsecutiveDays(arr){
var momentDates = arr.map(function(d){
return moment(d, "YYYY-MM-DD") ;
}).sort(function(a,b){return a.diff(b);})
var count = 0;
for(var i=1;i<momentDates.length;i++){
if(isConsecutive(momentDates[i-1],momentDates[i]))
count++;
}
return count+1;
}
A working example is below
function countConsecutiveDays(arr){
var momentDates = arr.map(function(d){
return moment(d, "YYYY-MM-DD") ;
}).sort(function(a,b){return a.diff(b);})
var count = 0;
for(var i=1;i<momentDates.length;i++){
if(isConsecutive(momentDates[i-1],momentDates[i]))
count++;
}
return count+1;
}
function isConsecutive(a,b){
return b.diff(a,"days") == 1
|| (a.weekday() == 5 && b.weekday() == 1 && b.diff(a,"days") == 3);
}
console.log(countConsecutiveDays( ["2017-03-07", "2017-03-09", "2017-03-10", "2017-03-13", "2017-03-15"]));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.js"></script>
This seems to be working from all my tests so far...unless someone can point out an issue or bug.
NOTE - This requires moment() library (https://momentjs.com)
var allDates = ["2017-03-07", "2017-03-09", "2017-03-10", "2017-03-13", "2017-03-15"];
var consecutive = 0;
allDates.sort(function(a,b){
return new Date(a) - new Date(b);
});
for (i = 2; i < allDates.length; i++) {
var d = moment(allDates[i], "YYYY-MM-DD");
var d1 = moment(allDates[i-1], "YYYY-MM-DD");
var d2 = moment(allDates[i-2], "YYYY-MM-DD");
if (d1.diff(d2,"days") == 1 && d.diff(d2,"days") == 2 ||
d2.weekday() == 5 && d1.weekday() == 1 && d1.diff(d2,"days") == 3 && d.diff(d1,"days") == 1 ||
d1.weekday() == 5 && d.weekday() == 1 && d.diff(d1,"days") == 3 && d1.diff(d2,"days") == 1) {
consecutive = 1;
break;
}
}
console.log('dates are consecutive: ' + consecutive)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.js"></script>

How do you return the resulting object in a function?

Good day, all! :)
For the past month, I have been working on a function to return 2 or more THREE.js materials in 1 function at 1 time. I've run into a small problem though. For some reason, I can't get this function to return the MeshBasicMaterial object AS WELL AS the MeshLambertMaterial data object. I KNOW my code is right because I've gone over it over 40 times already looking for errors.
Here's the WHOLE code:
/**
* A function for converting hex <-> dec w/o loss of precision.
*
* The problem is that parseInt("0x12345...") isn't precise enough to convert
* 64-bit integers correctly.
*
* Internally, this uses arrays to encode decimal digits starting with the least
* significant:
* 8 = [8]
* 16 = [6, 1]
* 1024 = [4, 2, 0, 1]
*/
// Adds two arrays for the given base (10 or 16), returning the result.
// This turns out to be the only "primitive" operation we need.
function add(x, y, base)
{
var z = [];
var n = Math.max(x.length, y.length);
var carry = 0;
var i = 0;
while (i < n || carry)
{
var xi = i < x.length ? x[i] : 0;
var yi = i < y.length ? y[i] : 0;
var zi = carry + xi + yi;
z.push(zi % base);
carry = Math.floor(zi / base);
i++;
}
return z;
}
// Returns a*x, where x is an array of decimal digits and a is an ordinary
// JavaScript number. base is the number base of the array x.
function multiplyByNumber(num, x, base)
{
if (num < 0) return null;
if (num == 0) return [];
var result = [];
var power = x;
while (true)
{
if (num & 1)
{
result = add(result, power, base);
}
num = num >> 1;
if (num === 0) break;
power = add(power, power, base);
}
return result;
}
function parseToDigitsArray(str, base)
{
var digits = str.split('');
var ary = [];
for (var i = digits.length - 1; i >= 0; i--)
{
var n = parseInt(digits[i], base);
if (isNaN(n)) return null;
ary.push(n);
}
return ary;
}
function convertBase(str, fromBase, toBase)
{
var digits = parseToDigitsArray(str, fromBase);
if (digits === null) return null;
var outArray = [];
var power = [1];
for (var i = 0; i < digits.length; i++)
{
// invariant: at this point, fromBase^i = power
if (digits[i])
{
outArray = add(outArray, multiplyByNumber(digits[i], power, toBase), toBase);
}
power = multiplyByNumber(fromBase, power, toBase);
}
var out = '';
for (var i = outArray.length - 1; i >= 0; i--)
{
out += outArray[i].toString(toBase);
}
return out;
}
function decToHex(decStr) {
var hex = convertBase(decStr, 10, 16);
return hex ? '0x' + hex : null;
}
function hexToDec(hexStr) {
if (hexStr.substring(0, 2) === '0x') hexStr = hexStr.substring(2);
hexStr = hexStr.toLowerCase();
return convertBase(hexStr, 16, 10);
}
function instr(str, val)
{
if(typeof(str) === 'string')
{
str = str.toString(str);
val = val.toString(val);
in_str = str.indexOf(val);
return in_str;
}
else
{
api_messagebox('Please use a string!');
}
return false;
}
function Get_RGBA(hexVal, getwhich)
{
hexVal = hexVal || '';
getwhich = getwhich || 0;
var commaSeperated = 0;
//if(typeof(hexVal) === 'string')
//{
// Removes the first character from the input string
if(hexVal.length === 8) { hexVal = hexVal.substring(1, hexVal.length); }
if(hexVal.length === 10) { hexVal = hexVal.substring(0, hexVal.length); }
// Now let's separate the pairs by a comma
for (var i = 0; i <= hexVal.length; i++)
{
// Iterate through each char of hexVal
// Copy each char of hexVal to commaSeperated
commaSeperated += hexVal.charAt(i);
// After each pair of characters add a comma, unless this
// is the last char
commaSeperated += (i % 2 == 1 && i != (hexVal.length - 1)) ? ',' : '';
}
// Lets now remove the 0x
if(instr(commaSeperated, '0x'))
{
commaSeperated = commaSeperated.substr(4);
}
if(instr(commaSeperated, ','))
{
// Lets now remove all "," 's
commaSeperated = commaSeperated.replace(/,/g, '');
if( getwhich < 0 ) { getwhich = 0; }
if( getwhich > 5 ) { getwhich = 5; }
alpha = [];
red = [];
green = [];
blue = [];
allcol = [];
sixcol = [];
alpha[0] = commaSeperated[0]+commaSeperated[1];
red[0] = commaSeperated[2]+commaSeperated[3];
green[0] = commaSeperated[4]+commaSeperated[5];
blue[0] = commaSeperated[6]+commaSeperated[7];
allcol[0] = alpha[0]+red[0]+green[0]+blue[0];
sixcol[0] = red[0]+green[0]+blue[0];
if( getwhich === 0 ) { fi_string = alpha[0]; }
if( getwhich === 1 ) { fi_string = red[0]; }
if( getwhich === 2 ) { fi_string = green[0]; }
if( getwhich === 3 ) { fi_string = blue[0]; }
if( getwhich === 4 ) { fi_string = allcol[0]; }
if( getwhich === 5 ) { fi_string = sixcol[0]; }
if( getwhich === 4 && fi_string.length != 10 || fi_string.length != 9 ) { getwhich = 5; }
if( getwhich === 5 && fi_string.length != 8 || fi_string.length != 7 ) { getwhich = 4; }
// Split the commaSeperated string by commas and return the array
return fi_string.toString();
}
//}
}
function isArray(myArray)
{
return myArray.constructor.toString();
//myArray.constructor.toString().indexOf("Array") > -1;
}
//EntityMaterial(0, 0, 0xFF44CFFC, 1, 0xFF000000, 4, 4, 0, 1.0, 0.8, "LambertBasicMaterial", 1)
function EntityMaterial(ptex, side, color, wire, wirecolor, col_type, col_wire_type, shading, transparent, opacity, mat_type, overdraw)
{
ptex = ptex || 0;
side = side || 0;
color = color || 0xFF006400;
wire = wire || 0;
wirecolor = wirecolor || 0xFF006400;
col_type = col_type || 4;
col_wire_type = col_wire_type || 4;
shading = shading || false;
transparent = transparent || 0.0;
opacity = opacity || 1.0;
mat_type = mat_type || "BasicMaterial";
overdraw = overdraw || true;
color = decToHex(color.toString());
wirecolor = decToHex(wirecolor.toString());
var gRGBA1 = Get_RGBA(color, col_type);
var gRGBA2 = Get_RGBA(wirecolor, col_wire_type);
var mat = 0;
if(mat_type === 'BasicMaterial')
{
this.materials = new THREE.MeshBasicMaterial
(
{
color: parseInt(gRGBA1, 16)
}
)
}
else if(mat_type === 'LambertMaterial')
{
this.materials = new THREE.MeshLambertMaterial
(
{
color: parseInt(gRGBA2, 16),
opacity: opacity,
wireframe: wire,
transparent: transparent
}
)
}
else if(mat_type === 'LambertBasicMaterial')
{
//new empty array.. could also be written as this.materials = new Array();
this.materials = [];
var mats = this.materials;
var basicMat = new THREE.MeshBasicMaterial( { color: parseInt(gRGBA1, 16) } );
var lambertMat = new THREE.MeshLambertMaterial( { color: parseInt(gRGBA2, 16), opacity: opacity, wireframe: wire, transparent: transparent } );
mats.push(basicMat);
mats.push(lambertMat);
api_messagebox(mats);
return mats;
}
}
Thank you so much!
Sincerely,
~Mythros
Right, I finally got around to trying it out and it all runs well for me.
To make sure we don't have any differences in environments take a look at the fiddle I made and let me know if it works for you as expected or if there's any other problems you need help with:
JSFiddle of original code
Small changes:
commented out the
api_messagebox(mats)
as it's undefined.
added lots of log statements so check out the web console.
Edit
I fixed the color problem by using THree.js' Color object as follows:
var color = new THREE.Color("rgb(0,0,255)");
But you may be doing this somewhere as the GET_RGBA function you are calling seems to be missing from the code you gave me.
As to making it wiremesh, I checked the Lambert object and it definitely had wiremesh = 1 set.
Make sure that the wire var you're passing is actually set to true, I set it explicitly in this updated fiddle

Which part is responsible on the animation in this script?

this code is from a jquery countdown counter , I am trying to eliminate the animation (flip) as you can see in the demo, I succeed to remove the main one, but if you notice at the end when a digit is at 0 you see a quick animation back to 9, and I could not figure which part is responsible for that, this is the code again here.
/*
* jquery-countdown plugin
*
* Copyright (c) 2009 Martin Conte Mac Donell <Reflejo#gmail.com>
* Dual licensed under the MIT and GPL licenses.
* http://docs.jquery.com/License
*
*/
// Draw digits in given container
var createDigits = function(where, options) {
var counter = 0;
// Iterate each startTime digit, if it is not a digit
// we'll asume that it's a separator
var mFirstPos, sFirstPos;
// reset digits and intervals array.
digits = [];
intervals = [];
for (var i = 0; i < options.startTime.length; i++) {
if (parseInt(options.startTime[i]) >= 0) {
elem = $('<div id="cnt_' + counter + '" class="cntDigit" />').css({
height: options.digitHeight,
float: 'left',
background: 'url(\'' + options.image + '\')',
width: options.digitWidth
});
elem.current = parseInt(options.startTime[i]);
digits.push(elem);
margin(counter, -elem.current * options.digitHeight * options.digitImages);
if (options.continuous === true) {
digits[counter]._max = function() { return 9; };
} else {
// Add max digits, for example, first digit of minutes (mm) has
// a max of 5. Conditional max is used when the left digit has reach
// the max. For example second "hours" digit has a conditional max of 4
switch (options.format[i]) {
case 'h':
digits[counter]._max = function(pos, isStart) {
if (pos % 2 == 0)
return 2;
else
return (isStart) ? 3: 9;
};
break;
case 'd':
digits[counter]._max = function() { return 9; };
break;
case 'm':
digits[counter]._max = function(pos) {
if(!mFirstPos) { mFirstPos = pos; }
return pos == mFirstPos ? 9 : 5;
};
break;
case 's':
digits[counter]._max = function(pos) {
if(!sFirstPos) { sFirstPos = pos; }
return pos == sFirstPos ? 9 : 5;
};
}
}
counter += 1;
} else {
elem = $('<div class="cntSeparator"/>').css({float: 'left'})
.text(options.startTime[i]);
}
where.append(elem)
}
};
var makeMovement = function(elem, steps, isForward, options) {
// Stop any other movement over the same digit.
if (intervals[elem])
window.clearInterval(intervals[elem]);
// Move to the initial position (We force that because in chrome
// there are some scenarios where digits lost sync)
var initialPos = -(options.digitHeight * options.digitImages *
digits[elem].current);
margin(elem, initialPos);
digits[elem].current = digits[elem].current + ((isForward) ? steps: -steps);
var x = 0;
intervals[elem] = setInterval(function() {
if (x++ === options.digitImages * steps) {
window.clearInterval(intervals[elem]);
delete intervals[elem];
return;
}
var diff = isForward ? -options.digitHeight: options.digitHeight;
margin(elem, initialPos + (x * diff));
}, options.stepTime / steps);
};
// Set or get element margin
var margin = function(elem, val) {
if (val !== undefined) {
digits[elem].margin = val;
return digits[elem].css({'backgroundPosition': '0 ' + val + 'px'});
}
return digits[elem].margin || 0;
};
// Makes the movement. This is done by "digitImages" steps.
var moveDigit = function(elem, options) {
if (digits[elem].current == 0) {
// Is there still time left?
if (elem > 0) {
var isStart = (digits[elem - 1].current == 0);
makeMovement(elem, digits[elem]._max(elem, isStart), true, options);
moveDigit(elem - 1, options);
} else { // That condition means that we reach the end! 00:00.
for (var i = 0; i < digits.length; i++) {
clearInterval(intervals[i]);
clearInterval(intervals.main);
margin(i, 0);
}
options.timerEnd();
}
return;
}
makeMovement(elem, 1, false, options);
};
// parses a date of the form hh:mm:ss, for example, where
// ... precision is the same as the format.
var parseRelativeDate = function(form, options) {
// give the date the values of now by default
var now = new Date();
var d = now.getDate();
var m = now.getMonth() + 1;
var y = now.getFullYear();
var h = now.getHours(), mm, s;
// read in components and render based on format
var format = options.format;
var parts = form.split(':');
if( format.indexOf('dd') == 0 ) {
d = parts[0];
parts = parts.slice(1);
format = format.substr(3);
}
if( format.indexOf('hh') == 0 ) {
h = parts[0];
parts = parts.slice(1);
format = format.substr(3);
}
if( format.indexOf('mm') == 0 ) {
mm = parts[0];
parts = parts.slice(1);
format = format.substr(3);
}
if( format.indexOf('ss') == 0 ) {
s = parts[0];
parts = parts.slice(1);
format = format.substr(3);
}
// return our constructed date object
return new Date([m, d, y].join('/') + ' ' + [h, mm, s].map(pad).join(':') + ' GMT-0900');
};
// convert a date object to the format specified
var formatCompute = function(d, options) {
var format = options.format;
var parse = {
d: d.getUTCDate() - 1,
h: d.getUTCHours(),
m: d.getUTCMinutes(),
s: d.getUTCSeconds()
};
return format.replace(/(dd|hh|mm|ss)/g, function($0, form) {
return pad(parse[form[0]]);
});
};
// add leading zeros
var pad = function(x){return (1e15+""+x).slice(-2)};
var digits = [];
var intervals = [];
jQuery.fn.countdown = function(userOptions) {
// Default options
var options = {
stepTime: 60,
// startTime and format MUST follow the same format.
// also you cannot specify a format unordered (e.g. hh:ss:mm is wrong)
format: "dd:hh:mm:ss",
startTime: "01:12:32:55",
digitImages: 6,
digitWidth: 67,
digitHeight: 90,
timerEnd: function(){},
image: "digits.png",
continuous: false
};
$.extend(options, userOptions);
// if an endTime is provided...
if( userOptions.endTime ) {
// calculate the difference between endTime and present time
var endDate = userOptions.endTime instanceof Date ? userOptions.endTime : parseRelativeDate(userOptions.endTime, options);
var diff = endDate.getTime() - (new Date()).getTime();
// and set that as the startTime
userOptions.startTime = formatCompute(new Date(diff), options);
delete userOptions.endTime;
}
$.extend(options, userOptions);
if (this.length) {
clearInterval(intervals.main);
createDigits(this, options);
intervals.main = setInterval(function(){ moveDigit(digits.length - 1, options); },
1000);
}
};
Is this:
setInterval(function(){ moveDigit(digits.length - 1, options); },
1000);
your animation has a duration of one second and this runs the function moveDigit()

Sort an array of objects by hour minutes in ascending order from earliest to latest

I have this code to sort an array of objects. The data in the objects is channel and time (hour, minutes). I want the sort to be by channels based on time from earliest to latest.
The channel data is accessed in this way:
channel_array[icount].data[0].hour
channel_array[icount].data[0].minutes
That data object array is like this and is already sorted:
[{hour:1, minutes:10},{hour:4, minutes:01}...]
Now all I need is to sort the channels from earliest to latest on the first element of the data array {hour:1, minutes: 10}. I do this with three nested loops. But this is not ideal. Is there a better way to do the sorting?
var current_time = new Date();
var current_hour = current_time.getHours();
var comp_hour = current_hour - 1;
for (var ih = 0; ih < 24; ih++) {
comp_hour += 1;
if (comp_hour == 24) { comp_hour = 0; }
for (var minutes = 0; minutes < 60; minutes++) {
for (var icount = 0; icount < channel_array.length; icount++) {
if (channel_array[icount].data.length > 0) {
var channel_hour = channel_array[icount].data[0].hour;
var channel_minutes = channel_array[icount].data[0].minutes;
var channel_phase = channel_array[icount].data[0].phase;
var next_day = channel_array[icount].data[0].next_day;
if (channel_phase.toLowerCase() == "pm" && channel_hour != 12) { channel_hour += 12; }
if ( parseInt(channel_hour) == parseInt(comp_hour) && parseInt(channel_minutes) == parseInt(minutes) && next_day != 1 ) {
channel_array_sort.push(channel_array[icount]);
}
}
}
}
}
Good lord, this is overcomplicated! How about just passing a custom comparator to Array.sort?
I'm honestly having a hard time figuring out exactly which array you are trying to sort, but in general, it would look something like this:
var input = [{hour:1, minutes:10},{hour:4, minutes: 1}, ...];
input.sort(function (a, b)
{
// compare hours first
if (a.hour < b.hour) return -1;
if (a.hour > b.hour) return 1;
// else a.hour === b.hour, so compare minutes to break the tie
if (a.minute < b.minute) return -1;
if (a.minute > b.minute) return 1;
// couldn't break the tie
return 0;
});
N.B. this performs an in-place sort, which means that the original array is modified. If that's not acceptable, just make a copy of the array before sorting it.
var input = /* same as before */;
var output = input.concat();
output.sort(function ()
{
// same as before
});
Starting point for the solution, from the OP:
channel_array_sort = channel_array.concat();
channel_array_sort.sort(function (a, b)
{
if (a.data == undefined || b.data == undefined) return 0;
if (a.data.length <= 0 || b.data.length <= 0) return 0;
// compare hours first
var a_hour = a.data[0].hour;
if (a.data[0].phase == "pm") a_hour += 12;
var b_hour = b.data[0].hour;
if (b.data[0].phase == "pm") b_hour += 12;
if (a_hour < b_hour) return -1;
if (a_hour > b_hour) return 1;
// else a.hour === b.hour, so compare minutes to break the tie
if (a.data[0].minutes < b.data[0].minutes) return -1;
if (a.data[0].minutes > b.data[0].minutes) return 1;
// couldn't break the tie
return 0;
});
var print_sort = JSON.stringify(channel_array_sort);
alert('print_sort b '+print_sort);

Categories

Resources