timeControlBlackBerry.js [plain text]
(function (){
var _type,
_currentDate,
_tzHours,
_tzMinutes,
_tzOffset = 0,
_min,
_max,
_step,
_shortMonthLabels,
_longMonthLabels,
_daysOfWeekLabels,
_amPmLabels,
_baseOffset,
_dragging = false,
_firstY = 0,
_scrollListener,
_endScrollListener;
var ITEM_HEIGHT = (screen.width === 720 && screen.height === 720) ? 91 : 99;
var TIME = 'Time',
DATE_TIME = 'DateTime',
DATE_TIME_LOCAL = 'DateTimeLocal',
DATE = 'Date',
MONTH = 'Month';
var HOURS = 'Hours',
MINUTES = 'Minutes',
YEARMONTHDATE = 'YearMonthDate',
YEAR = 'Year';
var COLUMNS = {};
COLUMNS[TIME] = [HOURS, MINUTES];
COLUMNS[DATE_TIME] = [YEARMONTHDATE, HOURS, MINUTES];
COLUMNS[DATE_TIME_LOCAL] = [YEARMONTHDATE, HOURS, MINUTES];
COLUMNS[DATE] = [DATE, MONTH, YEAR];
COLUMNS[MONTH] = [MONTH, YEAR];
var LIMIT_MIN = new Date(-62135596800000.0),
LIMIT_MAX = new Date(8640000000000000.0);
function parseFromDateString(str) {
var now = new Date(),
match;
if (str) {
switch (_type) {
case TIME:
match = str.match(/(\d+):(\d+)/);
_tzHours = match[1];
_tzMinutes = match[2];
_currentDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), _tzHours, _tzMinutes);
break;
case DATE:
match = str.match(/(\d+)-(\d+)-(\d+)/);
_currentDate = new Date(match[1], match[2] - 1, match[3]);
break;
case MONTH:
match = str.match(/(\d+)-(\d+)/);
_currentDate = new Date(match[1], match[2] - 1);
break;
case DATE_TIME: case DATE_TIME_LOCAL:
match = str.match(/(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)/);
var utcTime = new Date(match[1], match[2] - 1, match[3], match[4], match[5]);
if (match = str.match(/(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)+(\d+):(\d+)/)) { _tzHours = match[6];
_tzMinutes = match[7];
_tzOffset = (match[6] * 60 + match[7]) * 60000;
} else if (result = str.match(/(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)-(\d+):(\d+)/)) { _tzHours = match[6];
_tzMinutes = match[7];
_tzOffset = -(match[6] * 60 + match[7]) * 60000;
}
_currentDate = new Date(utcTime.getTime() + _tzOffset);
break;
}
} else {
switch (_type) {
case TIME:
case DATE_TIME:
case DATE_TIME_LOCAL:
_currentDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes());
break;
case DATE:
_currentDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
break;
case MONTH:
_currentDate = new Date(now.getFullYear(), now.getMonth());
break;
}
}
}
function padTwo(v) { return ('0' + v).substr(-2, 2); }
function padFour(v) { return ('000' + v).substr(-4, 4); }
function getResultString() {
switch(_type) {
case TIME:
return padTwo(_currentDate.getHours()) + ':' + padTwo(_currentDate.getMinutes());
case DATE_TIME: case DATE_TIME_LOCAL: var adjustedDate = new Date(_currentDate.getTime() - _tzOffset),
datetime = padFour(adjustedDate.getFullYear()) + '-' + padTwo(adjustedDate.getMonth() + 1) + '-' + padTwo(adjustedDate.getDate()) + 'T' + padTwo(adjustedDate.getHours()) + ':' + padTwo(adjustedDate.getMinutes());
if (_type === DATE_TIME_LOCAL) {
return datetime;
} else if (!_tzOffset) {
return datetime + 'Z';
} else if (_tzOffset > 0) {
return datetime + '+' + padTwo(_tzHours) + ':' + padTwo(_tzMinutes);
} else {
return datetime + '-' + padTwo(_tzHours) + ':' + padTwo(_tzMinutes);
}
case DATE:
return padFour(_currentDate.getFullYear()) + '-' + padTwo(_currentDate.getMonth() + 1) + '-' + padTwo(_currentDate.getDate());
case MONTH:
return padFour(_currentDate.getFullYear()) + '-' + padTwo(_currentDate.getMonth() + 1);
}
return '-1';
}
function ok() {
document.body.innerHTML = '';
window.setValueAndClosePopup(getResultString(), window.popUp);
}
function cancel() {
document.body.innerHTML = '';
window.setValueAndClosePopup('-1', window.popUp);
}
function adjustColumnLabelsForValue(col) {
var cloneDate = new Date(_currentDate.getTime()),
offset = Math.floor(col.children.length / 2);
switch(col.type) {
case HOURS:
cloneDate.setHours(cloneDate.getHours() - offset);
Array.prototype.forEach.call(col.children, function (child) {
child.innerText = padTwo(cloneDate.getHours());
cloneDate.setHours(cloneDate.getHours() + 1);
});
break;
case MINUTES:
cloneDate.setMinutes(cloneDate.getMinutes() - offset);
Array.prototype.forEach.call(col.children, function (child) {
child.innerText = padTwo(cloneDate.getMinutes());
cloneDate.setMinutes(cloneDate.getMinutes() + 1);
});
break;
case YEARMONTHDATE:
cloneDate.setDate(cloneDate.getDate() - offset);
Array.prototype.forEach.call(col.children, function (child) {
var dateMonth = document.createElement('div'),
weekday = document.createElement('div');
dateMonth.innerText = cloneDate.getDate() + ' ' + _shortMonthLabels[cloneDate.getMonth()]; weekday.innerText = _daysOfWeekLabels[cloneDate.getDay()];
child.innerHTML = '';
child.appendChild(dateMonth);
child.appendChild(weekday);
cloneDate.setDate(cloneDate.getDate() + 1);
});
break;
case DATE:
cloneDate.setDate(cloneDate.getDate() - offset);
Array.prototype.forEach.call(col.children, function (child) {
child.innerText = cloneDate.getDate();
cloneDate.setDate(cloneDate.getDate() + 1);
});
break;
case MONTH:
cloneDate.setDate(1); cloneDate.setMonth(cloneDate.getMonth() - offset);
Array.prototype.forEach.call(col.children, function (child) {
child.innerText = _longMonthLabels[cloneDate.getMonth()];
cloneDate.setMonth(cloneDate.getMonth() + 1);
});
break;
case YEAR:
cloneDate.setYear(cloneDate.getFullYear() - offset);
Array.prototype.forEach.call(col.children, function (child) {
child.innerText = padFour(cloneDate.getFullYear());
cloneDate.setYear(cloneDate.getFullYear() + 1);
});
break;
}
}
function beginScroll(evt) {
_dragging = true;
_firstY = evt.clientY || evt.touches[0].screenY;
_scrollListener = scroll.bind(this);
_endScrollListener = endScroll.bind(this);
document.addEventListener('mousemove', _scrollListener);
document.addEventListener('touchmove', _scrollListener);
document.addEventListener('mouseup', _endScrollListener);
document.addEventListener('touchend', _endScrollListener);
}
function scroll(evt) {
if (_dragging) {
var clientY = evt.clientY || evt.touches[0].screenY;
this.getElementsByClassName('tall-bit')[0].style.webkitTransform = 'translateY(' + (clientY - _firstY + _baseOffset) + 'px) translateZ(0)';
}
}
function endScroll(evt) {
if (!_dragging) {
return;
}
_dragging = false;
document.removeEventListener('mousemove', _scrollListener);
document.removeEventListener('touchmove', _scrollListener);
document.removeEventListener('mouseup', _endScrollListener);
document.removeEventListener('touchend', _endScrollListener);
var clientY = evt.clientY || evt.changedTouches[0].screenY;
var dy = clientY - _firstY,
dItems = Math.floor(dy / ITEM_HEIGHT),
extra = dy % ITEM_HEIGHT;
if (extra < 0) {
dItems++;
}
if (extra > ITEM_HEIGHT / 2) {
dItems++;
extra -= ITEM_HEIGHT;
} else if (extra < -ITEM_HEIGHT / 2) {
dItems--;
extra += ITEM_HEIGHT;
}
var oldDate = new Date(_currentDate.getTime());
switch(this.type) {
case HOURS:
case MINUTES:
case DATE:
case MONTH:
_currentDate['set' + this.type](_currentDate['get' + this.type]() - dItems);
break;
case YEAR:
_currentDate.setFullYear(_currentDate.getFullYear() - dItems);
break;
case YEARMONTHDATE:
_currentDate.setDate(_currentDate.getDate() - dItems);
break;
}
var tallBit = this.getElementsByClassName('tall-bit')[0];
tallBit.style.webkitTransition = '-webkit-transform ' + Math.abs(extra * 2) + 'ms ease-out';
tallBit.style.webkitTransform = 'translateY(' + (_baseOffset + dy - extra) + 'px) translateZ(0)';
setTimeout(function () {
tallBit.style.webkitTransition = '';
var tallBits = document.getElementsByClassName('tall-bit');
Array.prototype.forEach.call(tallBits, function (tall) {
switch(tall.type) {
case HOURS:
case MINUTES:
case DATE:
case MONTH:
if (oldDate['get' + tall.type]() !== _currentDate['get' + tall.type]()) {
adjustColumnLabelsForValue(tall);
}
break;
case YEAR:
if (oldDate.getFullYear() !== _currentDate.getFullYear()) {
adjustColumnLabelsForValue(tall);
}
break;
case YEARMONTHDATE:
if (oldDate.getFullYear() !== _currentDate.getFullYear()
|| oldDate.getMonth() !== _currentDate.getMonth()
|| oldDate.getDate() !== _currentDate.getDate()
) {
adjustColumnLabelsForValue(tall);
}
break;
}
});
resetPositions();
}, Math.abs(extra * 2) + 1);
}
function createColumn(type) {
var col = document.createElement('div'),
tallBit = document.createElement('div');
col.className = 'column ' + type;
col.type = type;
tallBit.className = 'tall-bit';
tallBit.type = type;
col.appendChild(tallBit);
var numCells = Math.ceil(Math.max(screen.height, screen.width) / ITEM_HEIGHT) * 2 + 1;
for (var i = 0; i < numCells; ++i) {
var cell = document.createElement('div');
cell.className = 'cell';
tallBit.appendChild(cell);
}
adjustColumnLabelsForValue(tallBit);
col.addEventListener('mousedown', beginScroll);
col.addEventListener('touchstart', beginScroll);
return col;
}
function resetPositions() {
var tallBits = document.getElementsByClassName('tall-bit');
Array.prototype.forEach.call(tallBits, function (tallBit) {
tallBit.style.webkitTransform = 'translateY(' + _baseOffset + 'px) translateZ(0)';
});
}
function show(pickerParams) {
_type = pickerParams.type;
parseFromDateString(pickerParams.initialValue);
_min = pickerParams.min; _max = pickerParams.max; _step = pickerParams.step;
_shortMonthLabels = pickerParams.uiText.shortMonthLabels;
_longMonthLabels = pickerParams.uiText.monthLabels;
_daysOfWeekLabels = pickerParams.uiText.daysOfWeekLabels;
_amPmLabels = pickerParams.uiText.amPmLabels;
if (!_currentDate) {
cancel();
}
if (_currentDate < LIMIT_MIN) {
_currentDate = new Date(LIMIT_MIN.getTime());
} else if (_currentDate > LIMIT_MAX) {
_currentDate = new Date(LIMIT_MAX.getTime());
}
var popup = document.createElement('div');
popup.className = popup.id = 'popup-area';
popup.dir = pickerParams.direction;
var header = document.createElement('div');
header.className = 'popup-header';
header.innerText = pickerParams.uiText.title;
popup.appendChild(header);
var content = document.createElement('div');
content.className = 'popup-content';
content.dir = 'ltr'; content.id = 'popup-content-time';
popup.appendChild(content);
COLUMNS[_type].forEach(function (type) {
content.appendChild(createColumn(type));
});
var rowHighlightContainer = document.createElement('div'),
filler1 = document.createElement('div'),
selectedRowHighlight = document.createElement('div'),
filler2 = document.createElement('div');
rowHighlightContainer.className = 'row-highlight-container';
selectedRowHighlight.className = 'row-highlight';
filler1.className = filler2.className = 'row-highlight-filler';
rowHighlightContainer.appendChild(filler1);
rowHighlightContainer.appendChild(selectedRowHighlight);
rowHighlightContainer.appendChild(filler2);
content.appendChild(rowHighlightContainer);
var okButton = document.createElement('button'),
cancelButton = document.createElement('button'),
buttons = document.createElement('div');
buttons.className = 'popup-buttons';
okButton.className = 'popup-button';
okButton.innerText = pickerParams.uiText.doneButtonLabel;
okButton.addEventListener('click', ok);
cancelButton.className = 'popup-button';
cancelButton.innerText = pickerParams.uiText.cancelButtonLabel;
cancelButton.addEventListener('click', cancel);
buttons.appendChild(cancelButton);
buttons.appendChild(okButton);
popup.appendChild(buttons);
document.body.appendChild(popup);
_baseOffset = Math.floor(document.getElementsByClassName('column')[0].clientHeight / 2 - document.getElementsByClassName('tall-bit')[0].clientHeight / 2);
resetPositions();
}
window.popupcontrol = window.popupcontrol || {};
window.popupcontrol.show = show;
}());