Which part is responsible on the animation in this script? - javascript

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

Related

MobiScroll datePicker reset value 00-000-0000

Mobiscroll date picker
every year should ends with reset value 00-000-0000, the reset value is achieved when i click the reset button. how to achieve this.
+----+-----+------+
| 31 | dec | 2014 |
| 00 | 000 | 0000 | ----->reset value
| 01 | jan | 2015 |
| 02 | jan | 2015 |
+----+-----+------+
--------------------
|ok| |reset| |cancel|
--------------------
To add reset value in the date picker scroll view. modify few lines of code in
mobiscroll.util.datetime.js, mobiscroll.datetimebase.js
In mobiscroll.datetimebase.js,
under variable defaults={}, add partialDate : false,
add reset values in a wheel generating loop: for (k = 0; k < 3; k++) {},
if (s.partialDate)
{
keys.push(-1);
values.push('0000');
}
replace following codes in a mobiscroll.datetimebase.js
formatValue: function (d) {
//return datetime.formatDate(format, getDate(d), s);
//KKN
if (d[o["m"]] != "-1" && d[o["d"]] != "0" )
{
datetime.partialDate = false;
return datetime.formatDate(format, getDate(d), s);
}
else
{
datetime.partialDate = true;
var tempDate = [],
hideDate = false,
hideMonth = false;
$.each(['y', 'm', 'd', 'a', 'h', 'i', 's'], function (x, i) {
tempDate[o[i]] = d[o[i]];
});
if (d[o["m"]] == "-1")
{
//datetime.partialDateFormat = yy;
tempDate[o["m"]] = "0";
tempDate[o["d"]] = "1";
hideMonth = true;
hideDate = true;
}else if (d[o["d"]] == "0"){
//datetime.partialDateFormat = MM-yy;
tempDate[o["d"]] = "1";
hideDate = true;
}
//var dt = getDate (tempDate);
var newDt = datetime.formatDate(format, getDate(tempDate), s, hideDate, hideMonth);
datetime.partialDateFormat = s.partialDateFormat;
return newDt;
}
//return datetime.formatPartialDate(format, d, s ,o);
},
parseValue: function (val) {
if (!val) {
innerValues = {};
}
var datValue = getArray(val ? datetime.parseDate(format, val, s) : (s.defaultValue || new Date()), !!val && !!val.getTime);
var seperator = "-";
if (format.indexOf ('/') > 0){
seperator = "/";
}
var dateArray = val.split(seperator);
switch (dateArray.length)
{
case 1: //Year Only
datValue[o["d"]] = 0;
datValue[o["m"]] = -1;
break;
case 2: //Month & Year
datValue[o["d"]] = 0;
break;
}
return datValue;
},
validate: function (dw, i, time, dir) {
//KKN
var temp = [],
hideDate = false,
hideMonth = false;
var d = inst.getArrayVal(true);
if (s.partialDate)
{
hideDate = false,
hideMonth = false;
$.each(['y', 'm', 'd', 'a', 'h', 'i', 's'], function (x, i) {
temp[o[i]] = d[o[i]];
});
if (d[o["m"]] == "-1")
{
temp[o["m"]] = "0";
temp[o["d"]] = "1";
hideMonth = true;
hideDate = true;
}else if (d[o["d"]] == "0"){
//datetime.partialDateFormat = MM-yy;
temp[o["d"]] = "1";
hideDate = true;
}
//return true;
}
else
{
var validated = getClosestValidDate(getDate(inst.getArrayVal(true)), dir),
temp = getArray(validated);
}
y = get(temp, 'y'),
m = get(temp, 'm'),
minprop = true,
maxprop = true;
$.each(['y', 'm', 'd', 'a', 'h', 'i', 's'], function (x, i) {
if (o[i] !== undefined) {
var min = mins[i],
max = maxs[i],
maxdays = 31,
val = get(temp, i),
t = $('.dw-ul', dw).eq(o[i]);
if (i == 'd') {
maxdays = s.getMaxDayOfMonth(y, m);
max = maxdays;
if (regen) {
$('.dw-li', t).each(function () {
var that = $(this),
d = that.data('val'),
w = s.getDate(y, m, d).getDay(),
str = dord.replace(/[my]/gi, '').replace(/dd/, (d < 10 ? '0' + d : d) + (s.daySuffix || '')).replace(/d/, d + (s.daySuffix || ''));
$('.dw-i', that).html(str.match(/DD/) ? str.replace(/DD/, '<span class="dw-day">' + s.dayNames[w] + '</span>') : str.replace(/D/, '<span class="dw-day">' + s.dayNamesShort[w] + '</span>'));
});
}
}
if (minprop && mind) {
min = f[i](mind);
}
if (maxprop && maxd) {
max = f[i](maxd);
}
if (i != 'y') {
var i1 = getIndex(t, min),
i2 = getIndex(t, max);
$('.dw-li', t).removeClass('dw-v').slice(i1, i2 + 1).addClass('dw-v');
if (i == 'd') { // Hide days not in month
//$('.dw-li', t).removeClass('dw-h').slice(maxdays).addClass('dw-h');
if (s.partialDate){
if (hideMonth)
{
$('.dw-li', t).removeClass('dw-h').slice(1).addClass('dw-h');
}
else{
$('.dw-li', t).removeClass('dw-h').slice(maxdays + 1).addClass('dw-h');
}
}
else
{
$('.dw-li', t).removeClass('dw-h').slice(maxdays).addClass('dw-h');
}
}
}
if (val < min) {
val = min;
}
if (val > max) {
val = max;
}
if (minprop) {
minprop = val == min;
}
if (maxprop) {
maxprop = val == max;
}
// Disable some days
if (i == 'd') {
var first = s.getDate(y, m, 1).getDay(),
idx = {};
// Set invalid indexes
validateDates(invalid, y, m, first, maxdays, idx, 1);
// Delete indexes which are valid
validateDates(valid, y, m, first, maxdays, idx, 0);
$.each(idx, function (i, v) {
if (v) {
$('.dw-li', t).eq(i).removeClass('dw-v');
}
});
}
}
});
// Invalid times
if (hasTime) {
$.each(['a', 'h', 'i', 's'], function (i, v) {
var val = get(temp, v),
d = get(temp, 'd'),
t = $('.dw-ul', dw).eq(o[v]);
if (o[v] !== undefined) {
validateTimes(invalid, i, v, temp, y, m, d, t, 0);
validateTimes(valid, i, v, temp, y, m, d, t, 1);
// Get valid value
validValues[i] = +inst.getValidCell(val, t, dir).val;
}
});
}
if (hideMonth)
{
temp[o["m"]] = "-1";
temp[o["d"]] = "0";
}else if (hideDate){
//datetime.partialDateFormat = MM-yy;
temp[o["d"]] = "0";
}
inst._tempWheelArray = temp;
}
and in mobiscroll.util.datetime.js, replace following lines
(function ($, undefined) {
var ms = $.mobiscroll;
ms.datetime = {
defaults: {
shortYearCutoff: '+10',
monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
dayNamesMin: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
amText: 'am',
pmText: 'pm',
getYear: function (d) { return d.getFullYear(); },
getMonth: function (d) { return d.getMonth(); },
getDay: function (d) { return d.getDate(); },
getDate: function (y, m, d, h, i, s, u) { return new Date(y, m, d, h || 0, i || 0, s || 0, u || 0); },
getMaxDayOfMonth: function (y, m, o) { return 32 - new Date(y, m, 32).getDate(); },
getWeekNumber: function (d) {
// Copy date so don't modify original
d = new Date(d);
d.setHours(0, 0, 0);
// Set to nearest Thursday: current date + 4 - current day number
// Make Sunday's day number 7
d.setDate(d.getDate() + 4 - (d.getDay() || 7));
// Get first day of year
var yearStart = new Date(d.getFullYear(), 0, 1);
// Calculate full weeks to nearest Thursday
return Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
}
},
/**
* Format a date into a string value with a specified format.
* #param {String} format Output format.
* #param {Date} date Date to format.
* #param {Object} [settings={}] Settings.
* #return {String} Returns the formatted date string.
*/
formatDate: function (format, date, settings, hideDate, hideMonth) {
var newformat = format;
if (!date) {
return null;
}
var s = $.extend({}, ms.datetime.defaults, settings),
look = function (m) { // Check whether a format character is doubled
var n = 0;
while (i + 1 < format.length && format.charAt(i + 1) == m) {
n++;
i++;
}
return n;
},
f1 = function (m, val, len) { // Format a number, with leading zero if necessary
var n = '' + val;
if (look(m)) {
while (n.length < len) {
n = '0' + n;
}
}
return n;
},
f2 = function (m, val, s, l) { // Format a name, short or long as requested
return (look(m) ? l[val] : s[val]);
},
f3 = function (m){
look(m);
if (newformat.indexOf('/') > 0 ){
newformat = newformat.replace( m +'/', '');
}
else
{
newformat = newformat.replace( m +'-', '');
}
newformat = newformat.replace( m, '');
if (format.charAt(i+1) == "/" ||format.charAt(i+1) == "-"){//Skip Separator
i++;
}
return '';
},
i,
year,
output = '',
literal = false;
//return s.getPartialMonth(date, format);
for (i = 0; i < format.length; i++) {
if (literal) {
if (format.charAt(i) == "'" && !look("'")) {
literal = false;
} else {
output += format.charAt(i);
}
} else {
switch (format.charAt(i)) {
case 'd':
if (hideDate)
{
output += f3('d');
}
else
{
output += f1('d', s.getDay(date), 2);
}
break;
case 'D':
if (hideDate)
{
output += f3('D');
}
else
{
output += f2('D', date.getDay(), s.dayNamesShort, s.dayNames);
}
break;
case 'o':
output += f1('o', (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
break;
case 'm':
if (hideMonth)
{
output += f3('m');
}
else
{
output += f1('m', s.getMonth(date) + 1, 2);
}
break;
case 'M':
if (hideMonth)
{
output += f3('M');
}
else
{
output += f2('M', s.getMonth(date), s.monthNamesShort, s.monthNames);
}
break;
case 'y':
year = s.getYear(date);
output += (look('y') ? year : (year % 100 < 10 ? '0' : '') + year % 100);
//output += (look('y') ? date.getFullYear() : (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
break;
case 'h':
var h = date.getHours();
output += f1('h', (h > 12 ? (h - 12) : (h === 0 ? 12 : h)), 2);
break;
case 'H':
output += f1('H', date.getHours(), 2);
break;
case 'i':
output += f1('i', date.getMinutes(), 2);
break;
case 's':
output += f1('s', date.getSeconds(), 2);
break;
case 'a':
output += date.getHours() > 11 ? s.pmText : s.amText;
break;
case 'A':
output += date.getHours() > 11 ? s.pmText.toUpperCase() : s.amText.toUpperCase();
break;
case "'":
if (look("'")) {
output += "'";
} else {
literal = true;
}
break;
default:
output += format.charAt(i);
}
}
}
ms.partialDateFormat = newformat;
return output;
},
/**
* Format a date into a string value with a specified format.
* #param {String} format Output format.
* #param {Date} date Date to format.
* #param {Object} [settings={}] Settings.
* #return {String} Returns the formatted date string.
*/
formatPartialDate: function (format, date, settings, o) {
if (!date) {
return null;
}
var tempDate = [],
hideDate = false,
hideMonth = false;
$.each(['y', 'm', 'd', 'a', 'h', 'i', 's'], function (x, i) {
tempDate[o[i]] = date[o[i]];
});
if (date[o["m"]] == "-1")
{
tempDate[o["m"]] = "0";
tempDate[o["d"]] = "1";
hideMonth = true;
hideDate = true;
}else if (date[o["d"]] == "0"){
tempDate[o["d"]] = "1";
hideDate = true;
}
var t2 = ms.getDate(tempDate);
var t1 = new Date();
//var output = ms.formatDate(format, settings.getDate(tempDate), settings, hideDate, hideMonth);
var output = ms.formatDate(format, tempDate, settings, hideDate, hideMonth);
return output;
},
/**
* Extract a date from a string value with a specified format.
* #param {String} format Input format.
* #param {String} value String to parse.
* #param {Object} [settings={}] Settings.
* #return {Date} Returns the extracted date.
*/
parseDate: function (format, value, settings) {
var s = $.extend({}, ms.datetime.defaults, settings),
def = s.defaultValue || new Date();
if (!format || !value) {
return def;
}
// If already a date object
if (value.getTime) {
return value;
}
value = (typeof value == 'object' ? value.toString() : value + '');
var seperator = "-";
if (format.indexOf ('/') > 0){
seperator = "/";
}
var dateArray = value.split(seperator);
//else (value)
var shortYearCutoff = s.shortYearCutoff,
year = s.getYear(def),
month = s.getMonth(def) + 1,
day = s.getDay(def),
doy = -1,
hours = def.getHours(),
minutes = def.getMinutes(),
seconds = 0, //def.getSeconds(),
ampm = -1,
literal = false, // Check whether a format character is doubled
lookAhead = function (match) {
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
if (matches) {
iFormat++;
}
return matches;
},
getNumber = function (match) { // Extract a number from the string value
lookAhead(match);
var size = (match == '#' ? 14 : (match == '!' ? 20 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)))),
digits = new RegExp('^\\d{1,' + size + '}'),
num = value.substr(iValue).match(digits);
if (!num) {
return 0;
}
iValue += num[0].length;
return parseInt(num[0], 10);
},
getName = function (match, s, l) { // Extract a name from the string value and convert to an index
var names = (lookAhead(match) ? l : s),
i;
for (i = 0; i < names.length; i++) {
if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
iValue += names[i].length;
return i + 1;
}
}
return 0;
},
checkLiteral = function () {
if (value.charAt(iValue) == '/' || value.charAt(iValue) == '-')
iValue++;
},
iValue = 0,
iFormat;
for (iFormat = 0; iFormat < format.length; iFormat++) {
if (literal) {
if (format.charAt(iFormat) == "'" && !lookAhead("'")) {
literal = false;
} else {
checkLiteral();
}
} else {
switch (format.charAt(iFormat)) {
case 'd':
if (dateArray.length <= 2){
day = 1;
//iValue++;
}
else{
day = getNumber('d');
}
break;
case 'D':
getName('D', s.dayNamesShort, s.dayNames);
break;
case 'o':
doy = getNumber('o');
break;
case 'm':
if (dateArray.length == 1){
month = 1;
//iValue++;
}
else
{
month = getNumber('m');
}
break;
case 'M':
if (dateArray.length == 1){
month = 1;
//iValue++;
}
else
{
month = getName('M', s.monthNamesShort, s.monthNames);
}
break;
case 'y':
year = getNumber('y');
break;
case 'H':
hours = getNumber('H');
break;
case 'h':
hours = getNumber('h');
break;
case 'i':
minutes = getNumber('i');
break;
case 's':
seconds = getNumber('s');
break;
case 'a':
ampm = getName('a', [s.amText, s.pmText], [s.amText, s.pmText]) - 1;
break;
case 'A':
ampm = getName('A', [s.amText, s.pmText], [s.amText, s.pmText]) - 1;
break;
case "'":
if (lookAhead("'")) {
checkLiteral();
} else {
literal = true;
}
break;
default:
checkLiteral();
}
}
}
if (year < 100) {
year += new Date().getFullYear() - new Date().getFullYear() % 100 +
(year <= (typeof shortYearCutoff != 'string' ? shortYearCutoff : new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)) ? 0 : -100);
}
if (doy > -1) {
month = 1;
day = doy;
do {
var dim = 32 - new Date(year, month - 1, 32).getDate();
if (day <= dim) {
break;
}
month++;
day -= dim;
} while (true);
}
hours = (ampm == -1) ? hours : ((ampm && hours < 12) ? (hours + 12) : (!ampm && hours == 12 ? 0 : hours));
var date = s.getDate(year, month - 1, day, hours, minutes, seconds);
if (s.getYear(date) != year || s.getMonth(date) + 1 != month || s.getDay(date) != day) {
return def; // Invalid date
}
return date;
}
};
// #deprecated since 2.11.0, backward compatibility code
// ---
ms.formatDate = ms.datetime.formatDate;
ms.parseDate = ms.datetime.parseDate;
ms.formatPartialDate = ms.datetime.formatPartialDate;
ms.getDate = ms.datetime.getDate;
ms.partialDate = true;
ms.partialDateFormat = ms.datetime.partialDateFormat; })(jQuery);
to enable a partial date picker add partialDate: true, whenever you want to enable a partial date picker.

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

Editing jquery-countdown to fit my HTML element

I've collected a nice jQuery countdown script from here. It needs no configuration but a great opensource project. But where I want to set is a smaller place like 50%. So, now I want to make it 50% on both width and height. First of all I opened digits.png with photoshop and made it 50%, then I opened jquery.countdown.js and the code is following:
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
};
var digits = [], intervals = [];
// Draw digits in given container
var createDigits = function(where)
{
var c = 0;
// Iterate each startTime digit, if it is not a digit
// we'll asume that it's a separator
for (var i = 0; i < options.startTime.length; i++)
{
if (parseInt(options.startTime[i]) >= 0)
{
elem = $('<div id="cnt_' + c + '" 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(c, -elem.current * options.digitHeight * options.digitImages);
if (options.continuous === true)
{
digits[c]._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[c]._max = function(pos, isStart) {
if (pos % 2 == 0)
return 2;
else
return (isStart) ? 3: 9;
};
break;
case 'd':
digits[c]._max = function(){ return 9; };
break;
case 'm':
case 's':
digits[c]._max = function(pos){ return (pos % 2 == 0) ? 5: 9; };
}
}
++c;
}
else
{
elem = $('<div class="cntSeparator"/>').css({float: 'left'})
.text(options.startTime[i]);
}
where.append(elem)
}
};
// 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;
};
var makeMovement = function(elem, steps, isForward)
{
// 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);
};
// Makes the movement. This is done by "digitImages" steps.
var moveDigit = function(elem)
{
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);
moveDigit(elem - 1);
}
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);
};
$.extend(options, userOptions);
createDigits(this);
intervals.main = setInterval(function(){ moveDigit(digits.length - 1); },
1000);
};
I tried changing some variables, digitWidth: 67 to digitWidth: 34 then digitHeight: 90 to digitHeight: 45 with no success. I want to make the countdown timer just half than the original. Can you suggest any change anywhere in the code, please?
Update: This is digits.png, 50% than original!
I also changed associated div's like #holder with no success.
Following is the current situation of the timer. The red marked places are the problems I mean misplaced.
You didn't resize digits.png correctly - it's too high, so digitHeight doesn't match your image.
See demo with an image that has 50% height (plugin code unchanged):
http://jsfiddle.net/lhoeppner/RGyPQ/
See the section with the image param:
$('#counter').countdown({
stepTime: 60,
digitWidth: 34,
digitHeight: 45,
format: 'hh:mm:ss',
startTime: "12:32:55",
timerEnd: function () {
alert('end!!');
},
image: "http://s21.postimg.org/nfgjv6b7r/digits2.png"
});

Add two timestamps of format "HH+:MM:SS"

So basically i have two strings of timestamps which i want to add:
a = "00:10:12";
aParts = a.split(/:/);
b = "00:30:34";
bParts = b.split(/:/);
time1 = 3600000 * parseInt(aParts[0]) + 60000 * parseInt(aParts[1]) + 1000 * parseInt(aParts[2]);
time2 = 3600000 * parseInt(bParts[0]) + 60000 * parseInt(bParts[1]) + 1000 * parseInt(bParts[2]);
dateTime = time1 + time2;
hours = parseInt(dateTime/3600000);
dateTime = parseInt(dateTime%3600000);
minutes = parseInt(dateTime/60000);
dateTime = parseInt(dateTime%60000);
seconds = parseInt(dateTime/1000);
newTime = addLeadingZeros(hours,2) + ':' + addLeadingZeros(minutes,2) + ':' + addLeadingZeros(seconds,2);
// returns correct "00:40:46"
function addLeadingZeros (n, length){
var str = (n > 0 ? n : -n) + "";
var zeros = "";
for (var i = length - str.length; i > 0; i--)
zeros += "0";
zeros += str;
return n >= 0 ? zeros : "-" + zeros;
}
While writing this question i managed to come up with the above code :-) that works somehow - is that a proper way of adding two string timestamps or is there a better approach?
Forgot to mention - i did try converting the two strings into Date objects and using .getTime() adding the two datetimes - but that gives me a wrong time in the date.
There is nothing notably wrong with your code, but be sure to set the radix when using parseInt
radix
An integer that represents the radix of the value to parse. Always
specify this parameter to eliminate reader confusion
and to guarantee predictable behavior. Different implementations
produce different results when a radix is not specified.
There is no standard method for performing the task that you have described.
Here is an example that I have used in the past.
Javascript
/*jslint maxerr: 50, indent: 4, browser: true, devel: true */
(function () {
"use strict";
function zeroPad(num) {
var str = num.toString();
if (num < 2) {
str = "0" + str;
}
return str;
}
function addTimes() {
if (!arguments.length) {
throw new SyntaxError("No arguments provided.");
}
var total = {
hours: 0,
minutes: 0,
seconds: 0
},
argIndex,
argLength,
time,
parts,
part,
partIndex,
temp;
for (argIndex = 0, argLength = arguments.length; argIndex < argLength; argIndex += 1) {
time = arguments[argIndex];
if (typeof time !== "string") {
throw new TypeError("Argument must be a string.");
}
parts = time.split(":");
if (parts.length !== 3) {
throw new SyntaxError("Argument is incorrectly formatted.");
}
for (partIndex = 0; partIndex < 3; partIndex += 1) {
part = parts[partIndex];
if (partIndex < 2) {
if (part === "" || !/^\d*$/.test(part)) {
throw new SyntaxError("Argument is incorrectly formatted.");
}
parts[partIndex] = parseInt(part, 10);
} else {
if (part === "" || !/^\d*\.?\d+$/.test(part)) {
throw new SyntaxError("Argument is incorrectly formatted.");
}
parts[partIndex] = parseFloat(part);
}
}
temp = (parts[2] + total.seconds);
total.seconds = temp % 60;
temp = (parts[1] + total.minutes) + (temp - total.seconds) / 60;
total.minutes = temp % 60;
total.hours = (parts[0] + total.hours) + (temp - total.minutes) / 60;
}
return zeroPad(total.hours) + ":" + zeroPad(total.minutes) + ":" + zeroPad(total.seconds);
}
var a = "00:10:12",
b = "00:30:34",
c = "10:40:40";
console.log(addTimes(a, b, c));
}());
Output
11:21:26
On jsfiddle

Check SSL certificate Expiration Date

I need to check local computer's SSl certificate expiry DATE and compare it with current date and notify user that his/her certificate is going to expire in X days. All this I need to do in JavaScript.
Your certificate should look like this:
-----BEGIN CERTIFICATE-----
MIIGoDCCBIigAwIBAgIJAICRY3cWdgK1MA0GCSqGSIb3DQEBCwUAMIGeMQswCQYD
VQQGEwJCRzERMA8GA1UECAwIQnVsZ2FyaWExDjAMBgNVBAcMBVNvZmlhMQ8wDQYD
..
ud5Nja8+xycA/Jk7bSvB1jJjpc3oL0G9j0HOcxqQKd4e1IQXuss5V7FnQxSOVCq4
GVK0r3LkAxtl/EGmQC1DRlHAUWg=
-----END CERTIFICATE-----
You need to strip the -----BEGIN CERTIFICATE----- header and the -----END CERTIFICATE----- trailer from the certificate data, the rest is a Base64 encoded byte array.
You need to decode it to an array of bytes (in this example represented as array of number, where each number represents a byte - number between 0 and 255 inclusive).
That byte array is a DER encoded ASN.1 structure as defined in RFC-5280.
The below example will parse the content of the certificate after the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- traile has already been stripped.
Usage:
var pem =
"MIIGijCCBXKgAwIBAgIQEpI/gkvDS6idH2m2Zwn7ZzANBgkqhkiG9w0BAQsFADCB\n"
...
+"VQ+o34uWo7z19I8eXWSXN6P+Uj1OvHn8zNM1G/ddjQXBwMvzwwJEdVBhdK1uQw==\n";
var bytes = fromBase64(pem);
var validity = getValidity(bytes);
var notBefore = validity.notBefore;
var notAfter = validity.notAfter;
var now = new Date();
if ( notBefore.getTime() < now.getTime()
&& now.getTime() < notAfter.getTime())
{
// Certificate is withing its validity days
} else {
// Certificate is either not yet valid or has already expired.
}
Parsing:
var TYPE_INTEGER = 0x02;
var TYPE_SEQUENCE = 0x10;
var TYPE_UTC_TIME = 0x17;
var TYPE_GENERALIZED_TIME = 0x18;
function subArray(original, start, end) {
var subArr = [];
var index = 0;
for (var i = start; i < end; i++) {
subArr[index++] = original[i];
}
return subArr;
}
function getDigit(d) {
switch (d) {
default:
case 0x30: case '0': return 0;
case 0x31: case '1': return 1;
case 0x32: case '2': return 2;
case 0x33: case '3': return 3;
case 0x34: case '4': return 4;
case 0x35: case '5': return 5;
case 0x36: case '6': return 6;
case 0x37: case '7': return 7;
case 0x38: case '8': return 8;
case 0x39: case '9': return 9;
}
}
function enterTag(bytes, start, requiredTypes, name) {
if (start + 1 > bytes.length) {
throw new Error("Too short certificate input");
}
var typeByte = bytes[start ] & 0x0FF;
var lenByte = bytes[start +1] & 0x0FF;
var type = typeByte & 0x1F;
var len = lenByte;
var index = start + 2;
if (requiredTypes.length > 0 && requiredTypes.indexOf(type) == -1) {
throw new Error("Invalid type");
}
var lengthOfLength = 0;
if (len > 0x07F) {
lengthOfLength = len & 0x7F;
len = 0;
for (var i =0; i < lengthOfLength && index < bytes.length; i++) {
len = (len << 8 ) | (bytes[index] & 0x00FF);
index++;
}
}
if (index >= bytes.length) {
throw new Error("Too short certificate input");
}
return {index: index, type: type, length: len}
}
function processTag(bytes, start, requiredTypes, name) {
var result = enterTag(bytes, start, requiredTypes, name);
var index = result.index + result.length;
if (index >= bytes.length) {
throw new Error("Too short certificate input");
}
var valueStart = result.index;
var valueEnd = result.index + result.length;
var value = subArray(bytes, valueStart, valueEnd);
return { index: index, type: result.type, value: value};
}
function readDate(bytes, start, name) {
var date = new Date();
var result = processTag(bytes, start,
[TYPE_UTC_TIME, TYPE_GENERALIZED_TIME], name);
var index, year;
if (result.type == 0x17) { // UTCTime
if (result.value.length < 12) {
throw new Error("Invalid type");
}
var yearHigh = getDigit(result.value[0]);
var yearLow = getDigit(result.value[1]);
var year2Digits = (yearHigh * 10 ) + (yearLow)
if (year2Digits >= 50) {
year = 1900 + year2Digits;
} else {
year = 2000 + year2Digits;
}
index = 2;
} else if (result.type = 0x18) { // GeneralizedTime
if (result.value.length < 14) {
throw new Error("Invalid type");
}
var year1 = getDigit(result.value[0]);
var year2 = getDigit(result.value[1]);
var year3 = getDigit(result.value[2]);
var year4 = getDigit(result.value[3]);
year = (year1 * 1000) + (year2 * 100) + (year3*10) + year4;
index = 4;
}
var monthHigh = getDigit(result.value[index++]);
var monthLow = getDigit(result.value[index++]);
var dayHigh = getDigit(result.value[index++]);
var dayhLow = getDigit(result.value[index++]);
var hourHigh = getDigit(result.value[index++]);
var hourLow = getDigit(result.value[index++]);
var minuteHigh = getDigit(result.value[index++]);
var minuteLow = getDigit(result.value[index++]);
var secondHigh = getDigit(result.value[index++]);
var secondLow = getDigit(result.value[index]);
var month = (monthHigh * 10) + monthLow;
var day = (dayHigh * 10) + dayhLow;
var hour = (hourHigh * 10) + hourLow;
var minute = (minuteHigh * 10) + minuteLow;
var second = (secondHigh * 10) + secondLow;
if (month < 1 || month > 12) {
throw new Error("Invalid month");
}
if (day < 1 || day > 31) {
throw new Error("Invalid day");
}
if (hour < 0 || hour > 24) {
throw new Error("Invalid hour");
}
if (minute < 0 || minute > 59) {
throw new Error("Invalid minute");
}
if (second < 0 || second > 59) {
throw new Error("Invalid second ");
}
date.setUTCFullYear(year);
date.setUTCMonth(month-1);
date.setUTCDate(day);
date.setUTCHours(hour);
date.setUTCMinutes(minute);
date.setUTCSeconds(second);
return {
index: result.index,
type: result.type,
length: result.length,
value: result.value,
date: date
};
}
function getValidity(bytes) {
if (bytes == null || bytes.length <= 0) {
return null;
}
var index = 0;
index = enterTag(bytes, index, [TYPE_SEQUENCE], "Certificate").index;
index = enterTag(bytes, index, [TYPE_SEQUENCE], "TBSCertificate").index;
var result = processTag(bytes, index, [0x00, 0x02],
"Version or SerialNumber");
if (result.type == 0) {
index = result.index;
result = processTag(bytes, index, [TYPE_INTEGER], "SerialNumber")
}
index = result.index;
result = processTag(bytes, index, [TYPE_SEQUENCE],
"Signature AlgorithmIdentifier");
index = result.index;
result = processTag(bytes, index, [], "Issuer Name");
index = result.index;
index = enterTag(bytes, index, [TYPE_SEQUENCE], "Validity").index;
result = readDate(bytes, index, "Not Before");
var notBefore = result.date;
index = result.index;
result = readDate(bytes, index, "Not After");
var notAfter = result.date;
return {notBefore: notBefore, notAfter: notAfter};
}
function getNextBase64Chr(str, index, equalSignReceived, alpha) {
var chr = null;
var code = 0;
var padding = equalSignReceived;
while (index < str.length) {
chr = str.charAt(index);
if (chr == " " || chr == "\r" || chr == "\n" || chr == "\t") {
index++;
continue;
}
if (chr == "=") {
padding = true;
} else {
if (equalSignReceived) {
throw new Error("Invalid Base64 Endcoding.");
}
code = alpha.indexOf(chr);
if (code == -1) {
throw new Error("Invalid Base64 Encoding .");
}
}
break;
}
return { character: chr, code: code, padding: padding, nextIndex: ++index};
}
function fromBase64(str) {
var alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var value = [];
var index = 0;
var destIndex = 0;
var padding = false;
while (true) {
var first = getNextBase64Chr(str, index, padding, alpha);
var second = getNextBase64Chr(str, first .nextIndex, first .padding, alpha);
var third = getNextBase64Chr(str, second.nextIndex, second.padding, alpha);
var fourth = getNextBase64Chr(str, third .nextIndex, third .padding, alpha);
index = fourth.nextIndex;
padding = fourth.padding;
// ffffffss sssstttt ttffffff
var base64_first = first.code == null ? 0 : first.code;
var base64_second = second.code == null ? 0 : second.code;
var base64_third = third.code == null ? 0 : third.code;
var base64_fourth = fourth.code == null ? 0 : fourth.code;
var a = (( base64_first << 2 ) & 0xFC ) | ((base64_second >> 4) & 0x03);
var b = (( base64_second << 4 ) & 0xF0 ) | ((base64_third >> 2) & 0x0F);
var c = (( base64_third << 6 ) & 0xC0 ) | ((base64_fourth >> 0) & 0x3F);
value [destIndex++] = a;
if (!third.padding) {
value [destIndex++] = b;
} else {
break;
}
if (!fourth.padding) {
value [destIndex++] = c;
} else {
break;
}
if (index >= str.length) {
break;
}
}
return value;
}
Used resources:
A Layman's Guide to a Subset of ASN.1, BER, and DER
Encoding of ASN.1 UTC Time and GeneralizedTime
RFC-5280
The only available option so far is forge - https://github.com/digitalbazaar/forge/blob/master/README.md or some sort of custom extension for the client.
Client side does not know nothing about other than DOM elements thus it cannot inspect SSL layer.
More on this Within a web browser, is it possible for JavaScript to obtain information about the SSL Certificate being used for the current page?
This is not possible from the client, but you could do something like this with node / shell combo.
Assuming you have access to the server the cert is running on you could do something like this on the host:
var execSync = require('child_process').execSync
var cmd = "echo | openssl s_client -connect 127.0.0.1:443 2>/dev/null | openssl x509 -noout -dates"
var stdout = execSync(cmd).toString()
// "notBefore=Feb 16 15:33:00 2017 GMT\nnotAfter=May 17 15:33:00 2017 GMT"
From there you could parse the dates reported by stdout and write them to a public resource or json file so they are readable from the client, and from there do your date comparison.

Categories

Resources