merge(third_party/git): Merge squashed git subtree at v2.23.0
Merge commit '1b593e1ea4' as 'third_party/git'
This commit is contained in:
commit
7ef0d62730
3629 changed files with 1139935 additions and 0 deletions
330
third_party/git/gitweb/static/js/adjust-timezone.js
vendored
Normal file
330
third_party/git/gitweb/static/js/adjust-timezone.js
vendored
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
// Copyright (C) 2011, John 'Warthog9' Hawley <warthog9@eaglescrag.net>
|
||||
// 2011, Jakub Narebski <jnareb@gmail.com>
|
||||
|
||||
/**
|
||||
* @fileOverview Manipulate dates in gitweb output, adjusting timezone
|
||||
* @license GPLv2 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get common timezone, add UI for changing timezones, and adjust
|
||||
* dates to use requested common timezone.
|
||||
*
|
||||
* This function is called during onload event (added to window.onload).
|
||||
*
|
||||
* @param {String} tzDefault: default timezone, if there is no cookie
|
||||
* @param {Object} tzCookieInfo: object literal with info about cookie to store timezone
|
||||
* @param {String} tzCookieInfo.name: name of cookie to store timezone
|
||||
* @param {String} tzClassName: denotes elements with date to be adjusted
|
||||
*/
|
||||
function onloadTZSetup(tzDefault, tzCookieInfo, tzClassName) {
|
||||
var tzCookieTZ = getCookie(tzCookieInfo.name, tzCookieInfo);
|
||||
var tz = tzDefault;
|
||||
|
||||
if (tzCookieTZ) {
|
||||
// set timezone to value saved in a cookie
|
||||
tz = tzCookieTZ;
|
||||
// refresh cookie, so its expiration counts from last use of gitweb
|
||||
setCookie(tzCookieInfo.name, tzCookieTZ, tzCookieInfo);
|
||||
}
|
||||
|
||||
// add UI for changing timezone
|
||||
addChangeTZ(tz, tzCookieInfo, tzClassName);
|
||||
|
||||
// server-side of gitweb produces datetime in UTC,
|
||||
// so if tz is 'utc' there is no need for changes
|
||||
var nochange = tz === 'utc';
|
||||
|
||||
// adjust dates to use specified common timezone
|
||||
fixDatetimeTZ(tz, tzClassName, nochange);
|
||||
}
|
||||
|
||||
|
||||
/* ...................................................................... */
|
||||
/* Changing dates to use requested timezone */
|
||||
|
||||
/**
|
||||
* Replace RFC-2822 dates contained in SPAN elements with tzClassName
|
||||
* CSS class with equivalent dates in given timezone.
|
||||
*
|
||||
* @param {String} tz: numeric timezone in '(-|+)HHMM' format, or 'utc', or 'local'
|
||||
* @param {String} tzClassName: specifies elements to be changed
|
||||
* @param {Boolean} nochange: markup for timezone change, but don't change it
|
||||
*/
|
||||
function fixDatetimeTZ(tz, tzClassName, nochange) {
|
||||
// sanity check, method should be ensured by common-lib.js
|
||||
if (!document.getElementsByClassName) {
|
||||
return;
|
||||
}
|
||||
|
||||
// translate to timezone in '(-|+)HHMM' format
|
||||
tz = normalizeTimezoneInfo(tz);
|
||||
|
||||
// NOTE: result of getElementsByClassName should probably be cached
|
||||
var classesFound = document.getElementsByClassName(tzClassName, "span");
|
||||
for (var i = 0, len = classesFound.length; i < len; i++) {
|
||||
var curElement = classesFound[i];
|
||||
|
||||
curElement.title = 'Click to change timezone';
|
||||
if (!nochange) {
|
||||
// we use *.firstChild.data (W3C DOM) instead of *.innerHTML
|
||||
// as the latter doesn't always work everywhere in every browser
|
||||
var epoch = parseRFC2822Date(curElement.firstChild.data);
|
||||
var adjusted = formatDateRFC2882(epoch, tz);
|
||||
|
||||
curElement.firstChild.data = adjusted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ...................................................................... */
|
||||
/* Adding triggers, generating timezone menu, displaying and hiding */
|
||||
|
||||
/**
|
||||
* Adds triggers for UI to change common timezone used for dates in
|
||||
* gitweb output: it marks up and/or creates item to click to invoke
|
||||
* timezone change UI, creates timezone UI fragment to be attached,
|
||||
* and installs appropriate onclick trigger (via event delegation).
|
||||
*
|
||||
* @param {String} tzSelected: pre-selected timezone,
|
||||
* 'utc' or 'local' or '(-|+)HHMM'
|
||||
* @param {Object} tzCookieInfo: object literal with info about cookie to store timezone
|
||||
* @param {String} tzClassName: specifies elements to install trigger
|
||||
*/
|
||||
function addChangeTZ(tzSelected, tzCookieInfo, tzClassName) {
|
||||
// make link to timezone UI discoverable
|
||||
addCssRule('.'+tzClassName + ':hover',
|
||||
'text-decoration: underline; cursor: help;');
|
||||
|
||||
// create form for selecting timezone (to be saved in a cookie)
|
||||
var tzSelectFragment = document.createDocumentFragment();
|
||||
tzSelectFragment = createChangeTZForm(tzSelectFragment,
|
||||
tzSelected, tzCookieInfo, tzClassName);
|
||||
|
||||
// event delegation handler for timezone selection UI (clicking on entry)
|
||||
// see http://www.nczonline.net/blog/2009/06/30/event-delegation-in-javascript/
|
||||
// assumes that there is no existing document.onclick handler
|
||||
document.onclick = function onclickHandler(event) {
|
||||
//IE doesn't pass in the event object
|
||||
event = event || window.event;
|
||||
|
||||
//IE uses srcElement as the target
|
||||
var target = event.target || event.srcElement;
|
||||
|
||||
switch (target.className) {
|
||||
case tzClassName:
|
||||
// don't display timezone menu if it is already displayed
|
||||
if (tzSelectFragment.childNodes.length > 0) {
|
||||
displayChangeTZForm(target, tzSelectFragment);
|
||||
}
|
||||
break;
|
||||
} // end switch
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create DocumentFragment with UI for changing common timezone in
|
||||
* which dates are shown in.
|
||||
*
|
||||
* @param {DocumentFragment} documentFragment: where attach UI
|
||||
* @param {String} tzSelected: default (pre-selected) timezone
|
||||
* @param {Object} tzCookieInfo: object literal with info about cookie to store timezone
|
||||
* @returns {DocumentFragment}
|
||||
*/
|
||||
function createChangeTZForm(documentFragment, tzSelected, tzCookieInfo, tzClassName) {
|
||||
var div = document.createElement("div");
|
||||
div.className = 'popup';
|
||||
|
||||
/* '<div class="close-button" title="(click on this box to close)">X</div>' */
|
||||
var closeButton = document.createElement('div');
|
||||
closeButton.className = 'close-button';
|
||||
closeButton.title = '(click on this box to close)';
|
||||
closeButton.appendChild(document.createTextNode('X'));
|
||||
closeButton.onclick = closeTZFormHandler(documentFragment, tzClassName);
|
||||
div.appendChild(closeButton);
|
||||
|
||||
/* 'Select timezone: <br clear="all">' */
|
||||
div.appendChild(document.createTextNode('Select timezone: '));
|
||||
var br = document.createElement('br');
|
||||
br.clear = 'all';
|
||||
div.appendChild(br);
|
||||
|
||||
/* '<select name="tzoffset">
|
||||
* ...
|
||||
* <option value="-0700">UTC-07:00</option>
|
||||
* <option value="-0600">UTC-06:00</option>
|
||||
* ...
|
||||
* </select>' */
|
||||
var select = document.createElement("select");
|
||||
select.name = "tzoffset";
|
||||
//select.style.clear = 'all';
|
||||
select.appendChild(generateTZOptions(tzSelected));
|
||||
select.onchange = selectTZHandler(documentFragment, tzCookieInfo, tzClassName);
|
||||
div.appendChild(select);
|
||||
|
||||
documentFragment.appendChild(div);
|
||||
|
||||
return documentFragment;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hide (remove from DOM) timezone change UI, ensuring that it is not
|
||||
* garbage collected and that it can be re-enabled later.
|
||||
*
|
||||
* @param {DocumentFragment} documentFragment: contains detached UI
|
||||
* @param {HTMLSelectElement} target: select element inside of UI
|
||||
* @param {String} tzClassName: specifies element where UI was installed
|
||||
* @returns {DocumentFragment} documentFragment
|
||||
*/
|
||||
function removeChangeTZForm(documentFragment, target, tzClassName) {
|
||||
// find containing element, where we appended timezone selection UI
|
||||
// `target' is somewhere inside timezone menu
|
||||
var container = target.parentNode, popup = target;
|
||||
while (container &&
|
||||
container.className !== tzClassName) {
|
||||
popup = container;
|
||||
container = container.parentNode;
|
||||
}
|
||||
// safety check if we found correct container,
|
||||
// and if it isn't deleted already
|
||||
if (!container || !popup ||
|
||||
container.className !== tzClassName ||
|
||||
popup.className !== 'popup') {
|
||||
return documentFragment;
|
||||
}
|
||||
|
||||
// timezone selection UI was appended as last child
|
||||
// see also displayChangeTZForm function
|
||||
var removed = popup.parentNode.removeChild(popup);
|
||||
if (documentFragment.firstChild !== removed) { // the only child
|
||||
// re-append it so it would be available for next time
|
||||
documentFragment.appendChild(removed);
|
||||
}
|
||||
// all of inline style was added by this script
|
||||
// it is not really needed to remove it, but it is a good practice
|
||||
container.removeAttribute('style');
|
||||
|
||||
return documentFragment;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display UI for changing common timezone for dates in gitweb output.
|
||||
* To be used from 'onclick' event handler.
|
||||
*
|
||||
* @param {HTMLElement} target: where to install/display UI
|
||||
* @param {DocumentFragment} tzSelectFragment: timezone selection UI
|
||||
*/
|
||||
function displayChangeTZForm(target, tzSelectFragment) {
|
||||
// for absolute positioning to be related to target element
|
||||
target.style.position = 'relative';
|
||||
target.style.display = 'inline-block';
|
||||
|
||||
// show/display UI for changing timezone
|
||||
target.appendChild(tzSelectFragment);
|
||||
}
|
||||
|
||||
|
||||
/* ...................................................................... */
|
||||
/* List of timezones for timezone selection menu */
|
||||
|
||||
/**
|
||||
* Generate list of timezones for creating timezone select UI
|
||||
*
|
||||
* @returns {Object[]} list of e.g. { value: '+0100', descr: 'GMT+01:00' }
|
||||
*/
|
||||
function generateTZList() {
|
||||
var timezones = [
|
||||
{ value: "utc", descr: "UTC/GMT"},
|
||||
{ value: "local", descr: "Local (per browser)"}
|
||||
];
|
||||
|
||||
// generate all full hour timezones (no fractional timezones)
|
||||
for (var x = -12, idx = timezones.length; x <= +14; x++, idx++) {
|
||||
var hours = (x >= 0 ? '+' : '-') + padLeft(x >=0 ? x : -x, 2);
|
||||
timezones[idx] = { value: hours + '00', descr: 'UTC' + hours + ':00'};
|
||||
if (x === 0) {
|
||||
timezones[idx].descr = 'UTC\u00B100:00'; // 'UTC±00:00'
|
||||
}
|
||||
}
|
||||
|
||||
return timezones;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate <options> elements for timezone select UI
|
||||
*
|
||||
* @param {String} tzSelected: default timezone
|
||||
* @returns {DocumentFragment} list of options elements to appendChild
|
||||
*/
|
||||
function generateTZOptions(tzSelected) {
|
||||
var elems = document.createDocumentFragment();
|
||||
var timezones = generateTZList();
|
||||
|
||||
for (var i = 0, len = timezones.length; i < len; i++) {
|
||||
var tzone = timezones[i];
|
||||
var option = document.createElement("option");
|
||||
if (tzone.value === tzSelected) {
|
||||
option.defaultSelected = true;
|
||||
}
|
||||
option.value = tzone.value;
|
||||
option.appendChild(document.createTextNode(tzone.descr));
|
||||
|
||||
elems.appendChild(option);
|
||||
}
|
||||
|
||||
return elems;
|
||||
}
|
||||
|
||||
|
||||
/* ...................................................................... */
|
||||
/* Event handlers and/or their generators */
|
||||
|
||||
/**
|
||||
* Create event handler that select timezone and closes timezone select UI.
|
||||
* To be used as $('select[name="tzselect"]').onchange handler.
|
||||
*
|
||||
* @param {DocumentFragment} tzSelectFragment: timezone selection UI
|
||||
* @param {Object} tzCookieInfo: object literal with info about cookie to store timezone
|
||||
* @param {String} tzCookieInfo.name: name of cookie to save result of selection
|
||||
* @param {String} tzClassName: specifies element where UI was installed
|
||||
* @returns {Function} event handler
|
||||
*/
|
||||
function selectTZHandler(tzSelectFragment, tzCookieInfo, tzClassName) {
|
||||
//return function selectTZ(event) {
|
||||
return function (event) {
|
||||
event = event || window.event;
|
||||
var target = event.target || event.srcElement;
|
||||
|
||||
var selected = target.options.item(target.selectedIndex);
|
||||
removeChangeTZForm(tzSelectFragment, target, tzClassName);
|
||||
|
||||
if (selected) {
|
||||
selected.defaultSelected = true;
|
||||
setCookie(tzCookieInfo.name, selected.value, tzCookieInfo);
|
||||
fixDatetimeTZ(selected.value, tzClassName);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create event handler that closes timezone select UI.
|
||||
* To be used e.g. as $('.closebutton').onclick handler.
|
||||
*
|
||||
* @param {DocumentFragment} tzSelectFragment: timezone selection UI
|
||||
* @param {String} tzClassName: specifies element where UI was installed
|
||||
* @returns {Function} event handler
|
||||
*/
|
||||
function closeTZFormHandler(tzSelectFragment, tzClassName) {
|
||||
//return function closeTZForm(event) {
|
||||
return function (event) {
|
||||
event = event || window.event;
|
||||
var target = event.target || event.srcElement;
|
||||
|
||||
removeChangeTZForm(tzSelectFragment, target, tzClassName);
|
||||
};
|
||||
}
|
||||
|
||||
/* end of adjust-timezone.js */
|
||||
Loading…
Add table
Add a link
Reference in a new issue