Browse Source

adding timeline

svn path=/branches/test/; revision=26382
tags/stw2018
Max Mehl 5 years ago
parent
commit
2f9e0f64de
100 changed files with 11805 additions and 0 deletions
  1. 92
    0
      timeline/api/ext/geochrono/geochrono-api.js
  2. 204
    0
      timeline/api/ext/geochrono/scripts/ether-painters.js
  3. 518
    0
      timeline/api/ext/geochrono/scripts/geochrono.js
  4. 10
    0
      timeline/api/ext/geochrono/scripts/l10n/en/labellers.js
  5. 52
    0
      timeline/api/ext/geochrono/scripts/labellers.js
  6. 86
    0
      timeline/api/ext/geochrono/scripts/units.js
  7. 92
    0
      timeline/api/ext/planning/planning-api.js
  8. 176
    0
      timeline/api/ext/planning/scripts/ether-painters.js
  9. 12
    0
      timeline/api/ext/planning/scripts/l10n/en/labellers.js
  10. 33
    0
      timeline/api/ext/planning/scripts/labellers.js
  11. 47
    0
      timeline/api/ext/planning/scripts/planning.js
  12. 66
    0
      timeline/api/ext/planning/scripts/units.js
  13. BIN
      timeline/api/images/blue-circle.png
  14. BIN
      timeline/api/images/bubble-bottom-arrow.png
  15. BIN
      timeline/api/images/bubble-bottom-left.png
  16. BIN
      timeline/api/images/bubble-bottom-right.png
  17. BIN
      timeline/api/images/bubble-bottom.png
  18. BIN
      timeline/api/images/bubble-left-arrow.png
  19. BIN
      timeline/api/images/bubble-left.png
  20. BIN
      timeline/api/images/bubble-right-arrow.png
  21. BIN
      timeline/api/images/bubble-right.png
  22. BIN
      timeline/api/images/bubble-top-arrow.png
  23. BIN
      timeline/api/images/bubble-top-left.png
  24. BIN
      timeline/api/images/bubble-top-right.png
  25. BIN
      timeline/api/images/bubble-top.png
  26. BIN
      timeline/api/images/close-button.png
  27. BIN
      timeline/api/images/copyright-vertical.png
  28. BIN
      timeline/api/images/copyright.png
  29. BIN
      timeline/api/images/dark-blue-circle.png
  30. BIN
      timeline/api/images/dark-green-circle.png
  31. BIN
      timeline/api/images/dark-red-circle.png
  32. BIN
      timeline/api/images/dull-blue-circle.png
  33. BIN
      timeline/api/images/dull-green-circle.png
  34. BIN
      timeline/api/images/dull-red-circle.png
  35. BIN
      timeline/api/images/gray-circle.png
  36. BIN
      timeline/api/images/green-circle.png
  37. BIN
      timeline/api/images/message-bottom-left.png
  38. BIN
      timeline/api/images/message-bottom-right.png
  39. BIN
      timeline/api/images/message-left.png
  40. BIN
      timeline/api/images/message-right.png
  41. BIN
      timeline/api/images/message-top-left.png
  42. BIN
      timeline/api/images/message-top-right.png
  43. BIN
      timeline/api/images/progress-running.gif
  44. BIN
      timeline/api/images/red-circle.png
  45. BIN
      timeline/api/images/top-bubble.png
  46. 733
    0
      timeline/api/scripts/band.js
  47. 1041
    0
      timeline/api/scripts/compact-painter.js
  48. 184
    0
      timeline/api/scripts/decorators.js
  49. 691
    0
      timeline/api/scripts/detailed-painter.js
  50. 576
    0
      timeline/api/scripts/ether-painters.js
  51. 305
    0
      timeline/api/scripts/ethers.js
  52. 64
    0
      timeline/api/scripts/event-utils.js
  53. 395
    0
      timeline/api/scripts/ext/japanese-eras.js
  54. 30
    0
      timeline/api/scripts/l10n/cs/labellers.js
  55. 9
    0
      timeline/api/scripts/l10n/cs/timeline.js
  56. 27
    0
      timeline/api/scripts/l10n/de/labellers.js
  57. 8
    0
      timeline/api/scripts/l10n/de/timeline.js
  58. 12
    0
      timeline/api/scripts/l10n/en/labellers.js
  59. 9
    0
      timeline/api/scripts/l10n/en/timeline.js
  60. 8
    0
      timeline/api/scripts/l10n/es/labellers.js
  61. 9
    0
      timeline/api/scripts/l10n/es/timeline.js
  62. 8
    0
      timeline/api/scripts/l10n/fr/labellers.js
  63. 9
    0
      timeline/api/scripts/l10n/fr/timeline.js
  64. 8
    0
      timeline/api/scripts/l10n/it/labellers.js
  65. 9
    0
      timeline/api/scripts/l10n/it/timeline.js
  66. 11
    0
      timeline/api/scripts/l10n/nl/labellers.js
  67. 9
    0
      timeline/api/scripts/l10n/nl/timeline.js
  68. 10
    0
      timeline/api/scripts/l10n/ru/labellers.js
  69. 9
    0
      timeline/api/scripts/l10n/ru/timeline.js
  70. 12
    0
      timeline/api/scripts/l10n/se/labellers.js
  71. 9
    0
      timeline/api/scripts/l10n/se/timeline.js
  72. 8
    0
      timeline/api/scripts/l10n/tr/labellers.js
  73. 9
    0
      timeline/api/scripts/l10n/tr/timeline.js
  74. 26
    0
      timeline/api/scripts/l10n/vi/labellers.js
  75. 9
    0
      timeline/api/scripts/l10n/vi/timeline.js
  76. 27
    0
      timeline/api/scripts/l10n/zh/labellers.js
  77. 9
    0
      timeline/api/scripts/l10n/zh/timeline.js
  78. 91
    0
      timeline/api/scripts/labellers.js
  79. 674
    0
      timeline/api/scripts/original-painter.js
  80. 258
    0
      timeline/api/scripts/overview-painter.js
  81. 567
    0
      timeline/api/scripts/sources.js
  82. 180
    0
      timeline/api/scripts/themes.js
  83. 645
    0
      timeline/api/scripts/timeline.js
  84. 68
    0
      timeline/api/scripts/units.js
  85. 120
    0
      timeline/api/styles/ethers.css
  86. 45
    0
      timeline/api/styles/events.css
  87. 65
    0
      timeline/api/styles/timeline.css
  88. 280
    0
      timeline/api/timeline-api.js
  89. 229
    0
      timeline/api/timeline-bundle.css
  90. 2835
    0
      timeline/api/timeline-bundle.js
  91. 77
    0
      timeline/fsfe.xml
  92. BIN
      timeline/graphics/blue-circle.psd
  93. BIN
      timeline/graphics/blue_stripes.png
  94. BIN
      timeline/graphics/bubble-arrows.png
  95. BIN
      timeline/graphics/bubble-body-and-arrows.png
  96. BIN
      timeline/graphics/bubble-body.png
  97. BIN
      timeline/graphics/bubble-bottom-arrow.png
  98. BIN
      timeline/graphics/bubble-bottom-left.png
  99. BIN
      timeline/graphics/bubble-bottom-right.png
  100. 0
    0
      timeline/graphics/bubble-bottom.png

+ 92
- 0
timeline/api/ext/geochrono/geochrono-api.js View File

@@ -0,0 +1,92 @@
/*==================================================
* Geochrono Extension
*
* This file will load all the Javascript files
* necessary to make the extension work.
*
*==================================================
*/
(function() {
var javascriptFiles = [
"geochrono.js",
"units.js",
"ether-painters.js",
"labellers.js"
];
var cssFiles = [
];
var localizedJavascriptFiles = [
"labellers.js"
];
var localizedCssFiles = [
];
// ISO-639 language codes, ISO-3166 country codes (2 characters)
var supportedLocales = [
"en" // English
];
try {
var includeJavascriptFile = function(filename) {
document.write("<script src='" + Timeline.urlPrefix + "ext/geochrono/scripts/" + filename + "' type='text/javascript'></script>");
};
var includeCssFile = function(filename) {
document.write("<link rel='stylesheet' href='" + Timeline.urlPrefix + "ext/geochrono/styles/" + filename + "' type='text/css'/>");
}
/*
* Include non-localized files
*/
for (var i = 0; i < javascriptFiles.length; i++) {
includeJavascriptFile(javascriptFiles[i]);
}
for (var i = 0; i < cssFiles.length; i++) {
includeCssFile(cssFiles[i]);
}
/*
* Include localized files
*/
var loadLocale = [];
var tryExactLocale = function(locale) {
for (var l = 0; l < supportedLocales.length; l++) {
if (locale == supportedLocales[l]) {
loadLocale[locale] = true;
return true;
}
}
return false;
}
var tryLocale = function(locale) {
if (tryExactLocale(locale)) {
return locale;
}
var dash = locale.indexOf("-");
if (dash > 0 && tryExactLocale(locale.substr(0, dash))) {
return locale.substr(0, dash);
}
return null;
}
tryLocale(Timeline.serverLocale);
tryLocale(Timeline.clientLocale);
for (var l = 0; l < supportedLocales.length; l++) {
var locale = supportedLocales[l];
if (loadLocale[locale]) {
for (var i = 0; i < localizedJavascriptFiles.length; i++) {
includeJavascriptFile("l10n/" + locale + "/" + localizedJavascriptFiles[i]);
}
for (var i = 0; i < localizedCssFiles.length; i++) {
includeCssFile("l10n/" + locale + "/" + localizedCssFiles[i]);
}
}
}
} catch (e) {
alert(e);
}
})();

+ 204
- 0
timeline/api/ext/geochrono/scripts/ether-painters.js View File

@@ -0,0 +1,204 @@
/*==================================================
* Geochrono Ether Painter
*==================================================
*/
Timeline.GeochronoEtherPainter = function(params, band, timeline) {
this._params = params;
this._intervalUnit = params.intervalUnit;
this._multiple = ("multiple" in params) ? params.multiple : 1;
this._theme = params.theme;
};

Timeline.GeochronoEtherPainter.prototype.initialize = function(band, timeline) {
this._band = band;
this._timeline = timeline;
this._backgroundLayer = band.createLayerDiv(0);
this._backgroundLayer.setAttribute("name", "ether-background"); // for debugging
this._backgroundLayer.style.background = this._theme.ether.backgroundColors[band.getIndex()];
this._markerLayer = null;
this._lineLayer = null;
var align = ("align" in this._params && typeof this._params.align == "string") ? this._params.align :
this._theme.ether.interval.marker[timeline.isHorizontal() ? "hAlign" : "vAlign"];
var showLine = ("showLine" in this._params) ? this._params.showLine :
this._theme.ether.interval.line.show;
this._intervalMarkerLayout = new Timeline.GeochronoEtherMarkerLayout(
this._timeline, this._band, this._theme, align, showLine);
this._highlight = new Timeline.EtherHighlight(
this._timeline, this._band, this._theme, this._backgroundLayer);
}

Timeline.GeochronoEtherPainter.prototype.setHighlight = function(startDate, endDate) {
this._highlight.position(startDate, endDate);
}

Timeline.GeochronoEtherPainter.prototype.paint = function() {
if (this._markerLayer) {
this._band.removeLayerDiv(this._markerLayer);
}
this._markerLayer = this._band.createLayerDiv(100);
this._markerLayer.setAttribute("name", "ether-markers"); // for debugging
this._markerLayer.style.display = "none";
if (this._lineLayer) {
this._band.removeLayerDiv(this._lineLayer);
}
this._lineLayer = this._band.createLayerDiv(1);
this._lineLayer.setAttribute("name", "ether-lines"); // for debugging
this._lineLayer.style.display = "none";
var minDate = Math.ceil(Timeline.GeochronoUnit.toNumber(this._band.getMinDate()));
var maxDate = Math.floor(Timeline.GeochronoUnit.toNumber(this._band.getMaxDate()));
var increment;
var hasMore;
(function(intervalUnit, multiple) {
var dates;
switch (intervalUnit) {
case Timeline.GeochronoUnit.AGE:
dates = Timeline.Geochrono.ages; break;
case Timeline.GeochronoUnit.EPOCH:
dates = Timeline.Geochrono.epoches; break;
case Timeline.GeochronoUnit.PERIOD:
dates = Timeline.Geochrono.periods; break;
case Timeline.GeochronoUnit.ERA:
dates = Timeline.Geochrono.eras; break;
case Timeline.GeochronoUnit.EON:
dates = Timeline.Geochrono.eons; break;
default:
hasMore = function() {
return minDate > 0 && minDate > maxDate;
}
increment = function() {
minDate -= multiple;
};
return;
}
var startIndex = dates.length - 1;
while (startIndex > 0) {
if (minDate <= dates[startIndex].start) {
break;
}
startIndex--;
}
minDate = dates[startIndex].start;
hasMore = function() {
return startIndex < (dates.length - 1) && minDate > maxDate;
};
increment = function() {
startIndex++;
minDate = dates[startIndex].start;
};
})(this._intervalUnit, this._multiple);
var labeller = this._band.getLabeller();
while (true) {
this._intervalMarkerLayout.createIntervalMarker(
Timeline.GeochronoUnit.fromNumber(minDate),
labeller,
this._intervalUnit,
this._markerLayer,
this._lineLayer
);
if (hasMore()) {
increment();
} else {
break;
}
}
this._markerLayer.style.display = "block";
this._lineLayer.style.display = "block";
};

Timeline.GeochronoEtherPainter.prototype.softPaint = function() {
};


/*==================================================
* Geochrono Ether Marker Layout
*==================================================
*/
Timeline.GeochronoEtherMarkerLayout = function(timeline, band, theme, align, showLine) {
var horizontal = timeline.isHorizontal();
if (horizontal) {
if (align == "Top") {
this.positionDiv = function(div, offset) {
div.style.left = offset + "px";
div.style.top = "0px";
};
} else {
this.positionDiv = function(div, offset) {
div.style.left = offset + "px";
div.style.bottom = "0px";
};
}
} else {
if (align == "Left") {
this.positionDiv = function(div, offset) {
div.style.top = offset + "px";
div.style.left = "0px";
};
} else {
this.positionDiv = function(div, offset) {
div.style.top = offset + "px";
div.style.right = "0px";
};
}
}
var markerTheme = theme.ether.interval.marker;
var lineTheme = theme.ether.interval.line;
var stylePrefix = (horizontal ? "h" : "v") + align;
var labelStyler = markerTheme[stylePrefix + "Styler"];
var emphasizedLabelStyler = markerTheme[stylePrefix + "EmphasizedStyler"];
this.createIntervalMarker = function(date, labeller, unit, markerDiv, lineDiv) {
var offset = Math.round(band.dateToPixelOffset(date));

if (showLine) {
var divLine = timeline.getDocument().createElement("div");
divLine.style.position = "absolute";
if (lineTheme.opacity < 100) {
SimileAjax.Graphics.setOpacity(divLine, lineTheme.opacity);
}
if (horizontal) {
divLine.style.borderLeft = "1px solid " + lineTheme.color;
divLine.style.left = offset + "px";
divLine.style.width = "1px";
divLine.style.top = "0px";
divLine.style.height = "100%";
} else {
divLine.style.borderTop = "1px solid " + lineTheme.color;
divLine.style.top = offset + "px";
divLine.style.height = "1px";
divLine.style.left = "0px";
divLine.style.width = "100%";
}
lineDiv.appendChild(divLine);
}
var label = labeller.labelInterval(date, unit);
var div = timeline.getDocument().createElement("div");
div.innerHTML = label.text;
div.style.position = "absolute";
(label.emphasized ? emphasizedLabelStyler : labelStyler)(div);
this.positionDiv(div, offset);
markerDiv.appendChild(div);
return div;
};
};

+ 518
- 0
timeline/api/ext/geochrono/scripts/geochrono.js View File

@@ -0,0 +1,518 @@
/*==================================================
* Geochrono
*==================================================
*/
Timeline.Geochrono = new Object();
Timeline.Geochrono.eons = [
{ name: "Proterozoic",
start: 2500.000
},
{ name: "Phanerozoic",
start: 542.000
}
];
Timeline.Geochrono.eras = [
{ name: "Paleoarchean",
start: 3600.000
},
{ name: "Mesoarchean",
start: 3200.000
},
{ name: "Neoarchean",
start: 2800.000
},
{ name: "Paleoproterozoic",
start: 2500.000
},
{ name: "Mesoproterozoic",
start: 1600.000
},
{ name: "Neoproterozoic",
start: 1000.000
},
{ name: "Paleozoic",
start: 542.000
},
{ name: "Mesozoic",
start: 251.000
},
{ name: "Cenozoic",
start: 65.500
}
];
Timeline.Geochrono.periods = [
{ name: "Siderian",
start: 2500.000
},
{ name: "Rhyacian",
start: 2300.000
},
{ name: "Orosirian",
start: 2050.000
},
{ name: "Statherian",
start: 1800.000
},
{ name: "Calymmian",
start: 1600.000
},
{ name: "Ectasian",
start: 1400.000
},
{ name: "Stenian",
start: 1200.000
},
{ name: "Tonian",
start: 1000.000
},
{ name: "Cryogenian",
start: 850.000
},
{ name: "Ediacaran",
start: 600.000
},
{ name: "Cambrian",
start: 542.000
},
{ name: "Ordovician",
start: 488.300
},
{ name: "Silurian",
start: 443.700
},
{ name: "Devonian",
start: 416.000
},
{ name: "Carboniferous",
start: 359.200
},
{ name: "Permian",
start: 299.000
},
{ name: "Triassic",
start: 251.000
},
{ name: "Jurassic",
start: 199.600
},
{ name: "Cretaceous",
start: 145.500
},
{ name: "Paleogene",
start: 65.500
},
{ name: "Neogene",
start: 23.030
}
];
Timeline.Geochrono.epoches = [
{ name: "Lower Cambrian",
start: 542.000
},
{ name: "Middle Cambrian",
start: 513.000
},
{ name: "Furongian",
start: 501.000
},
{ name: "Lower Ordovician",
start: 488.300
},
{ name: "Middle Ordovician",
start: 471.800
},
{ name: "Upper Ordovician",
start: 460.900
},
{ name: "Llandovery",
start: 443.700
},
{ name: "Wenlock",
start: 428.200
},
{ name: "Ludlow",
start: 422.900
},
{ name: "Pridoli",
start: 418.700
},
{ name: "Lower Devonian",
start: 416.000
},
{ name: "Middle Devonian",
start: 397.500
},
{ name: "Upper Devonian",
start: 385.300
},
{ name: "Mississippian",
start: 359.200
},
{ name: "Pennsylvanian",
start: 318.100
},
{ name: "Cisuralian",
start: 299.000
},
{ name: "Guadalupian",
start: 270.600
},
{ name: "Lopingian",
start: 260.400
},
{ name: "Lower Triassic",
start: 251.000
},
{ name: "Middle Triassic",
start: 245.000
},
{ name: "Upper Triassic",
start: 228.000
},
{ name: "Lower Jurassic",
start: 199.600
},
{ name: "Middle Jurassic",
start: 175.600
},
{ name: "Upper Jurassic",
start: 161.200
},
{ name: "Lower Cretaceous",
start: 145.500
},
{ name: "Upper Cretaceous",
start: 99.600
},
{ name: "Paleocene",
start: 65.500
},
{ name: "Eocene",
start: 55.800
},
{ name: "Oligocene",
start: 33.900
},
{ name: "Miocene",
start: 23.030
},
{ name: "Pliocene",
start: 5.332
},
{ name: "Pleistocene",
start: 1.806
},
{ name: "Holocene",
start: 0.012
}
];
Timeline.Geochrono.ages = [
{ name: "-",
start: 542.000
},
{ name: "-",
start: 513.000
},
{ name: "Paibian",
start: 501.000
},
{ name: "Tremadocian",
start: 488.300
},
{ name: "-",
start: 478.600
},
{ name: "-",
start: 471.800
},
{ name: "Darriwilian",
start: 468.100
},
{ name: "-",
start: 460.900
},
{ name: "-",
start: 455.800
},
{ name: "Hirnantian",
start: 445.600
},
{ name: "Rhuddanian",
start: 443.700
},
{ name: "Aeronian",
start: 439.000
},
{ name: "Telychian",
start: 436.100
},
{ name: "Sheinwoodian",
start: 428.200
},
{ name: "Homerian",
start: 426.200
},
{ name: "Gorstian",
start: 422.900
},
{ name: "Ludfordian",
start: 421.300
},
{ name: "-",
start: 418.700
},
{ name: "Lochkovian",
start: 416.000
},
{ name: "Pragian",
start: 411.200
},
{ name: "Emsian",
start: 407.000
},
{ name: "Eifelian",
start: 397.500
},
{ name: "Givetian",
start: 391.800
},
{ name: "Frasnian",
start: 385.300
},
{ name: "Famennian",
start: 374.500
},
{ name: "Tournaisian",
start: 359.200
},
{ name: "Visean",
start: 345.300
},
{ name: "Serpukhovian",
start: 326.400
},
{ name: "Bashkirian",
start: 318.100
},
{ name: "Moscovian",
start: 311.700
},
{ name: "Kazimovian",
start: 306.500
},
{ name: "Gzhelian",
start: 303.900
},
{ name: "Asselian",
start: 299.000
},
{ name: "Sakmarian",
start: 294.600
},
{ name: "Artinskian",
start: 284.400
},
{ name: "Kungurian",
start: 275.600
},
{ name: "Roadian",
start: 270.600
},
{ name: "Wordian",
start: 268.000
},
{ name: "Capitanian",
start: 265.800
},
{ name: "Wuchiapingian",
start: 260.400
},
{ name: "Changhsingian",
start: 253.800
},
{ name: "Induan",
start: 251.000
},
{ name: "Olenekian",
start: 249.700
},
{ name: "Anisian",
start: 245.000
},
{ name: "Ladinian",
start: 237.000
},
{ name: "Carnian",
start: 228.000
},
{ name: "Norian",
start: 216.500
},
{ name: "Rhaetian",
start: 203.600
},
{ name: "Hettangian",
start: 199.600
},
{ name: "Sinemurian",
start: 196.500
},
{ name: "Pliensbachian",
start: 189.600
},
{ name: "Toarcian",
start: 183.000
},
{ name: "Aalenian",
start: 175.600
},
{ name: "Bajocian",
start: 171.600
},
{ name: "Bathonian",
start: 167.700
},
{ name: "Callovian",
start: 164.700
},
{ name: "Oxfordian",
start: 161.200
},
{ name: "Kimmeridgian",
start: 155.000
},
{ name: "Tithonian",
start: 150.800
},
{ name: "Berriasian",
start: 145.500
},
{ name: "Valanginian",
start: 140.200
},
{ name: "Hauterivian",
start: 136.400
},
{ name: "Barremian",
start: 130.000
},
{ name: "Aptian",
start: 125.000
},
{ name: "Albian",
start: 112.000
},
{ name: "Cenomanian",
start: 99.600
},
{ name: "Turonian",
start: 93.500
},
{ name: "Coniacian",
start: 89.300
},
{ name: "Santonian",
start: 85.800
},
{ name: "Campanian",
start: 83.500
},
{ name: "Maastrichtian",
start: 70.600
},
{ name: "Danian",
start: 65.500
},
{ name: "Selandian",
start: 61.700
},
{ name: "Thanetian",
start: 58.700
},
{ name: "Ypresian",
start: 55.800
},
{ name: "Lutetian",
start: 48.600
},
{ name: "Bartonian",
start: 40.400
},
{ name: "Priabonian",
start: 37.200
},
{ name: "Rupelian",
start: 33.900
},
{ name: "Chattian",
start: 28.400
},
{ name: "Aquitanian",
start: 23.030
},
{ name: "Burdigalian",
start: 20.430
},
{ name: "Langhian",
start: 15.970
},
{ name: "Serravallian",
start: 13.650
},
{ name: "Tortonian",
start: 11.608
},
{ name: "Messinian",
start: 7.246
},
{ name: "Zanclean",
start: 5.332
},
{ name: "Piacenzian",
start: 3.600
},
{ name: "Gelasian",
start: 2.588
}
];

Timeline.Geochrono.createBandInfo = function(params) {
var theme = ("theme" in params) ? params.theme : Timeline.getDefaultTheme();
var eventSource = ("eventSource" in params) ? params.eventSource : null;
var ether = new Timeline.LinearEther({
centersOn: ("date" in params) ? params.date : Timeline.GeochronoUnit.makeDefaultValue(),
interval: 1,
pixelsPerInterval: params.intervalPixels
});
var etherPainter = new Timeline.GeochronoEtherPainter({
intervalUnit: params.intervalUnit,
multiple: ("multiple" in params) ? params.multiple : 1,
align: params.align,
theme: theme
});
var eventPainterParams = {
theme: theme
};
if ("trackHeight" in params) {
eventPainterParams.trackHeight = params.trackHeight;
}
if ("trackGap" in params) {
eventPainterParams.trackGap = params.trackGap;
}
var eventPainter = ("overview" in params && params.overview) ?
new Timeline.OverviewEventPainter(eventPainterParams) :
new Timeline.DetailedEventPainter(eventPainterParams);
return {
width: params.width,
eventSource: eventSource,
timeZone: ("timeZone" in params) ? params.timeZone : 0,
ether: ether,
etherPainter: etherPainter,
eventPainter: eventPainter
};
};

+ 10
- 0
timeline/api/ext/geochrono/scripts/l10n/en/labellers.js View File

@@ -0,0 +1,10 @@
/*==================================================
* Localization of Geochrono Labeller
*==================================================
*/

Timeline.GeochronoLabeller.eonNames["en"] = Timeline.Geochrono.eons;
Timeline.GeochronoLabeller.eraNames["en"] = Timeline.Geochrono.eras;
Timeline.GeochronoLabeller.periodNames["en"] = Timeline.Geochrono.periods;
Timeline.GeochronoLabeller.epochNames["en"] = Timeline.Geochrono.epoches;
Timeline.GeochronoLabeller.ageNames["en"] = Timeline.Geochrono.ages;

+ 52
- 0
timeline/api/ext/geochrono/scripts/labellers.js View File

@@ -0,0 +1,52 @@
/*==================================================
* Geochrono Labeller
*==================================================
*/

Timeline.GeochronoLabeller = function(locale) {
this._locale = locale;
};

Timeline.GeochronoLabeller.eonNames = [];
Timeline.GeochronoLabeller.eraNames = [];
Timeline.GeochronoLabeller.periodNames = [];
Timeline.GeochronoLabeller.epochNames = [];
Timeline.GeochronoLabeller.ageNames = [];

Timeline.GeochronoLabeller.prototype.labelInterval = function(date, intervalUnit) {
var n = Timeline.GeochronoUnit.toNumber(date);
var dates, names;
switch (intervalUnit) {
case Timeline.GeochronoUnit.AGE:
dates = Timeline.Geochrono.ages;
names = Timeline.GeochronoLabeller.ageNames; break;
case Timeline.GeochronoUnit.EPOCH:
dates = Timeline.Geochrono.epoches;
names = Timeline.GeochronoLabeller.epochNames; break;
case Timeline.GeochronoUnit.PERIOD:
dates = Timeline.Geochrono.periods;
names = Timeline.GeochronoLabeller.periodNames; break;
case Timeline.GeochronoUnit.ERA:
dates = Timeline.Geochrono.eras;
names = Timeline.GeochronoLabeller.eraNames; break;
case Timeline.GeochronoUnit.EON:
dates = Timeline.Geochrono.eons;
names = Timeline.GeochronoLabeller.eonNames; break;
default:
return { text: n, emphasized: false };
}
for (var i = dates.length - 1; i >= 0; i--) {
if (n <= dates[i].start) {
return {
text: names[this._locale][i].name,
emphasized: n == dates[i].start
}
}
}
return { text: n, emphasized: false };
};

Timeline.GeochronoLabeller.prototype.labelPrecise = function(date) {
return Timeline.GeochronoUnit.toNumber(date) + "ma";
};

+ 86
- 0
timeline/api/ext/geochrono/scripts/units.js View File

@@ -0,0 +1,86 @@
/*==================================================
* Geochrono Unit
*==================================================
*/
Timeline.GeochronoUnit = new Object();
Timeline.GeochronoUnit.MA = 0;
Timeline.GeochronoUnit.AGE = 1;
Timeline.GeochronoUnit.EPOCH = 2;
Timeline.GeochronoUnit.PERIOD = 3;
Timeline.GeochronoUnit.ERA = 4;
Timeline.GeochronoUnit.EON = 5;
Timeline.GeochronoUnit.getParser = function(format) {
return Timeline.GeochronoUnit.parseFromObject;
};
Timeline.GeochronoUnit.createLabeller = function(locale, timeZone) {
return new Timeline.GeochronoLabeller(locale);
};
Timeline.GeochronoUnit.wrapMA = function (n) {
return new Timeline.GeochronoUnit._MA(n);
};
Timeline.GeochronoUnit.makeDefaultValue = function () {
return Timeline.GeochronoUnit.wrapMA(0);
};
Timeline.GeochronoUnit.cloneValue = function (v) {
return new Timeline.GeochronoUnit._MA(v._n);
};
Timeline.GeochronoUnit.parseFromObject = function(o) {
if (o instanceof Timeline.GeochronoUnit._MA) {
return o;
} else if (typeof o == "number") {
return Timeline.GeochronoUnit.wrapMA(o);
} else if (typeof o == "string" && o.length > 0) {
return Timeline.GeochronoUnit.wrapMA(Number(o));
} else {
return null;
}
};
Timeline.GeochronoUnit.toNumber = function(v) {
return v._n;
};
Timeline.GeochronoUnit.fromNumber = function(n) {
return new Timeline.GeochronoUnit._MA(n);
};
Timeline.GeochronoUnit.compare = function(v1, v2) {
var n1, n2;
if (typeof v1 == "object") {
n1 = v1._n;
} else {
n1 = Number(v1);
}
if (typeof v2 == "object") {
n2 = v2._n;
} else {
n2 = Number(v2);
}
return n2 - n1;
};
Timeline.GeochronoUnit.earlier = function(v1, v2) {
return Timeline.GeochronoUnit.compare(v1, v2) < 0 ? v1 : v2;
};
Timeline.GeochronoUnit.later = function(v1, v2) {
return Timeline.GeochronoUnit.compare(v1, v2) > 0 ? v1 : v2;
};
Timeline.GeochronoUnit.change = function(v, n) {
return new Timeline.GeochronoUnit._MA(v._n - n);
};
Timeline.GeochronoUnit._MA = function(n) {
this._n = n;
};

+ 92
- 0
timeline/api/ext/planning/planning-api.js View File

@@ -0,0 +1,92 @@
/*==================================================
* Planning Extension
*
* This file will load all the Javascript files
* necessary to make the extension work.
*
*==================================================
*/
(function() {
var javascriptFiles = [
"planning.js",
"units.js",
"ether-painters.js",
"labellers.js"
];
var cssFiles = [
];
var localizedJavascriptFiles = [
"labellers.js"
];
var localizedCssFiles = [
];
// ISO-639 language codes, ISO-3166 country codes (2 characters)
var supportedLocales = [
"en" // English
];
try {
var includeJavascriptFile = function(filename) {
document.write("<script src='" + Timeline.urlPrefix + "ext/planning/scripts/" + filename + "' type='text/javascript'></script>");
};
var includeCssFile = function(filename) {
document.write("<link rel='stylesheet' href='" + Timeline.urlPrefix + "ext/planning/styles/" + filename + "' type='text/css'/>");
}
/*
* Include non-localized files
*/
for (var i = 0; i < javascriptFiles.length; i++) {
includeJavascriptFile(javascriptFiles[i]);
}
for (var i = 0; i < cssFiles.length; i++) {
includeCssFile(cssFiles[i]);
}
/*
* Include localized files
*/
var loadLocale = [];
var tryExactLocale = function(locale) {
for (var l = 0; l < supportedLocales.length; l++) {
if (locale == supportedLocales[l]) {
loadLocale[locale] = true;
return true;
}
}
return false;
}
var tryLocale = function(locale) {
if (tryExactLocale(locale)) {
return locale;
}
var dash = locale.indexOf("-");
if (dash > 0 && tryExactLocale(locale.substr(0, dash))) {
return locale.substr(0, dash);
}
return null;
}
tryLocale(Timeline.serverLocale);
tryLocale(Timeline.clientLocale);
for (var l = 0; l < supportedLocales.length; l++) {
var locale = supportedLocales[l];
if (loadLocale[locale]) {
for (var i = 0; i < localizedJavascriptFiles.length; i++) {
includeJavascriptFile("l10n/" + locale + "/" + localizedJavascriptFiles[i]);
}
for (var i = 0; i < localizedCssFiles.length; i++) {
includeCssFile("l10n/" + locale + "/" + localizedCssFiles[i]);
}
}
}
} catch (e) {
alert(e);
}
})();

+ 176
- 0
timeline/api/ext/planning/scripts/ether-painters.js View File

@@ -0,0 +1,176 @@
/*==================================================
* Planning Ether Painter
*==================================================
*/
Timeline.PlanningEtherPainter = function(params, band, timeline) {
this._params = params;
this._intervalUnit = params.intervalUnit;
this._multiple = ("multiple" in params) ? params.multiple : 1;
this._theme = params.theme;
};

Timeline.PlanningEtherPainter.prototype.initialize = function(band, timeline) {
this._band = band;
this._timeline = timeline;
this._backgroundLayer = band.createLayerDiv(0);
this._backgroundLayer.setAttribute("name", "ether-background"); // for debugging
this._backgroundLayer.style.background = this._theme.ether.backgroundColors[band.getIndex()];
this._markerLayer = null;
this._lineLayer = null;
var align = ("align" in this._params && typeof this._params.align == "string") ? this._params.align :
this._theme.ether.interval.marker[timeline.isHorizontal() ? "hAlign" : "vAlign"];
var showLine = ("showLine" in this._params) ? this._params.showLine :
this._theme.ether.interval.line.show;
this._intervalMarkerLayout = new Timeline.PlanningEtherMarkerLayout(
this._timeline, this._band, this._theme, align, showLine);
this._highlight = new Timeline.EtherHighlight(
this._timeline, this._band, this._theme, this._backgroundLayer);
}

Timeline.PlanningEtherPainter.prototype.setHighlight = function(startDate, endDate) {
this._highlight.position(startDate, endDate);
}

Timeline.PlanningEtherPainter.prototype.paint = function() {
if (this._markerLayer) {
this._band.removeLayerDiv(this._markerLayer);
}
this._markerLayer = this._band.createLayerDiv(100);
this._markerLayer.setAttribute("name", "ether-markers"); // for debugging
this._markerLayer.style.display = "none";
if (this._lineLayer) {
this._band.removeLayerDiv(this._lineLayer);
}
this._lineLayer = this._band.createLayerDiv(1);
this._lineLayer.setAttribute("name", "ether-lines"); // for debugging
this._lineLayer.style.display = "none";
var minDate = Math.max(0, Math.ceil(Timeline.PlanningUnit.toNumber(this._band.getMinDate())));
var maxDate = Math.floor(Timeline.PlanningUnit.toNumber(this._band.getMaxDate()));
var hasMore = function() {
return minDate < maxDate;
};
var change = 1;
var multiple = this._multiple;
switch (this._intervalUnit) {
case Timeline.PlanningUnit.DAY: change = 1; break;
case Timeline.PlanningUnit.WEEK: change = 7; break;
case Timeline.PlanningUnit.MONTH: change = 28; break;
case Timeline.PlanningUnit.QUARTER: change = 28 * 3; break;
case Timeline.PlanningUnit.YEAR: change = 28 * 12; break;
}
var increment = function() {
minDate += change * multiple;
};
var labeller = this._band.getLabeller();
while (true) {
this._intervalMarkerLayout.createIntervalMarker(
Timeline.PlanningUnit.fromNumber(minDate),
labeller,
this._intervalUnit,
this._markerLayer,
this._lineLayer
);
if (hasMore()) {
increment();
} else {
break;
}
}
this._markerLayer.style.display = "block";
this._lineLayer.style.display = "block";
};

Timeline.PlanningEtherPainter.prototype.softPaint = function() {
};


/*==================================================
* Planning Ether Marker Layout
*==================================================
*/
Timeline.PlanningEtherMarkerLayout = function(timeline, band, theme, align, showLine) {
var horizontal = timeline.isHorizontal();
if (horizontal) {
if (align == "Top") {
this.positionDiv = function(div, offset) {
div.style.left = offset + "px";
div.style.top = "0px";
};
} else {
this.positionDiv = function(div, offset) {
div.style.left = offset + "px";
div.style.bottom = "0px";
};
}
} else {
if (align == "Left") {
this.positionDiv = function(div, offset) {
div.style.top = offset + "px";
div.style.left = "0px";
};
} else {
this.positionDiv = function(div, offset) {
div.style.top = offset + "px";
div.style.right = "0px";
};
}
}
var markerTheme = theme.ether.interval.marker;
var lineTheme = theme.ether.interval.line;
var stylePrefix = (horizontal ? "h" : "v") + align;
var labelStyler = markerTheme[stylePrefix + "Styler"];
var emphasizedLabelStyler = markerTheme[stylePrefix + "EmphasizedStyler"];
this.createIntervalMarker = function(date, labeller, unit, markerDiv, lineDiv) {
var offset = Math.round(band.dateToPixelOffset(date));

if (showLine) {
var divLine = timeline.getDocument().createElement("div");
divLine.style.position = "absolute";
if (lineTheme.opacity < 100) {
Timeline.Graphics.setOpacity(divLine, lineTheme.opacity);
}
if (horizontal) {
divLine.style.borderLeft = "1px solid " + lineTheme.color;
divLine.style.left = offset + "px";
divLine.style.width = "1px";
divLine.style.top = "0px";
divLine.style.height = "100%";
} else {
divLine.style.borderTop = "1px solid " + lineTheme.color;
divLine.style.top = offset + "px";
divLine.style.height = "1px";
divLine.style.left = "0px";
divLine.style.width = "100%";
}
lineDiv.appendChild(divLine);
}
var label = labeller.labelInterval(date, unit);
var div = timeline.getDocument().createElement("div");
div.innerHTML = label.text;
div.style.position = "absolute";
(label.emphasized ? emphasizedLabelStyler : labelStyler)(div);
this.positionDiv(div, offset);
markerDiv.appendChild(div);
return div;
};
};

+ 12
- 0
timeline/api/ext/planning/scripts/l10n/en/labellers.js View File

@@ -0,0 +1,12 @@
/*==================================================
* Localization of Planning Labeller
*==================================================
*/

Timeline.PlanningLabeller.labels["en"] = {
dayPrefix: "d",
weekPrefix: "w",
monthPrefix: "m",
quarterPrefix: "q",
yearPrefix: "y"
};

+ 33
- 0
timeline/api/ext/planning/scripts/labellers.js View File

@@ -0,0 +1,33 @@
/*==================================================
* Planning Labeller
*==================================================
*/

Timeline.PlanningLabeller = function(locale) {
this._locale = locale;
};

Timeline.PlanningLabeller.labels = [];

Timeline.PlanningLabeller.prototype.labelInterval = function(date, intervalUnit) {
var n = Timeline.PlanningUnit.toNumber(date);
var prefix = "";
var divider = 1;
var divider2 = 7;
var labels = Timeline.PlanningLabeller.labels[this._locale];
switch (intervalUnit) {
case Timeline.PlanningUnit.DAY: prefix = labels.dayPrefix; break;
case Timeline.PlanningUnit.WEEK: prefix = labels.weekPrefix; divider = 7; divider2 = divider * 4; break;
case Timeline.PlanningUnit.MONTH: prefix = labels.monthPrefix; divider = 28; divider2 = divider * 3; break;
case Timeline.PlanningUnit.QUARTER: prefix = labels.quarterPrefix; divider = 28 * 3; divider2 = divider * 4; break;
case Timeline.PlanningUnit.YEAR: prefix = labels.yearPrefix; divider = 28 * 12; divider2 = divider * 5; break;
}
return { text: prefix + Math.floor(n / divider), emphasized: (n % divider2) == 0 };
};

Timeline.PlanningLabeller.prototype.labelPrecise = function(date) {
return Timeline.PlanningLabeller.labels[this._locale].dayPrefix +
Timeline.PlanningUnit.toNumber(date);
};

+ 47
- 0
timeline/api/ext/planning/scripts/planning.js View File

@@ -0,0 +1,47 @@
/*==================================================
* Planning
*==================================================
*/

Timeline.Planning = new Object();

Timeline.Planning.createBandInfo = function(params) {
var theme = ("theme" in params) ? params.theme : Timeline.getDefaultTheme();
var eventSource = ("eventSource" in params) ? params.eventSource : null;
var ether = new Timeline.LinearEther({
centersOn: ("date" in params) ? params.date : Timeline.PlanningUnit.makeDefaultValue(),
interval: 1,
pixelsPerInterval: params.intervalPixels
});
var etherPainter = new Timeline.PlanningEtherPainter({
intervalUnit: params.intervalUnit,
multiple: ("multiple" in params) ? params.multiple : 1,
align: params.align,
theme: theme
});
var eventPainterParams = {
theme: theme
};
if ("trackHeight" in params) {
eventPainterParams.trackHeight = params.trackHeight;
}
if ("trackGap" in params) {
eventPainterParams.trackGap = params.trackGap;
}
var eventPainter = ("overview" in params && params.overview) ?
new Timeline.OverviewEventPainter(eventPainterParams) :
new Timeline.DetailedEventPainter(eventPainterParams);
return {
width: params.width,
eventSource: eventSource,
timeZone: ("timeZone" in params) ? params.timeZone : 0,
ether: ether,
etherPainter: etherPainter,
eventPainter: eventPainter
};
};

+ 66
- 0
timeline/api/ext/planning/scripts/units.js View File

@@ -0,0 +1,66 @@
/*==================================================
* Planning Unit
*==================================================
*/

Timeline.PlanningUnit = new Object();

Timeline.PlanningUnit.DAY = 0;
Timeline.PlanningUnit.WEEK = 1;
Timeline.PlanningUnit.MONTH = 2;
Timeline.PlanningUnit.QUARTER = 3;
Timeline.PlanningUnit.YEAR = 4;

Timeline.PlanningUnit.getParser = function(format) {
return Timeline.PlanningUnit.parseFromObject;
};

Timeline.PlanningUnit.createLabeller = function(locale, timeZone) {
return new Timeline.PlanningLabeller(locale);
};

Timeline.PlanningUnit.makeDefaultValue = function () {
return 0;
};

Timeline.PlanningUnit.cloneValue = function (v) {
return v;
};

Timeline.PlanningUnit.parseFromObject = function(o) {
if (o == null) {
return null;
} else if (typeof o == "number") {
return o;
} else {
try {
return parseInt(o);
} catch (e) {
return null;
}
}
};

Timeline.PlanningUnit.toNumber = function(v) {
return v
};

Timeline.PlanningUnit.fromNumber = function(n) {
return n;
};

Timeline.PlanningUnit.compare = function(v1, v2) {
return v1 - v2;
};

Timeline.PlanningUnit.earlier = function(v1, v2) {
return Timeline.PlanningUnit.compare(v1, v2) < 0 ? v1 : v2;
};

Timeline.PlanningUnit.later = function(v1, v2) {
return Timeline.PlanningUnit.compare(v1, v2) > 0 ? v1 : v2;
};

Timeline.PlanningUnit.change = function(v, n) {
return v + n;
};

BIN
timeline/api/images/blue-circle.png View File


BIN
timeline/api/images/bubble-bottom-arrow.png View File


BIN
timeline/api/images/bubble-bottom-left.png View File


BIN
timeline/api/images/bubble-bottom-right.png View File


BIN
timeline/api/images/bubble-bottom.png View File


BIN
timeline/api/images/bubble-left-arrow.png View File


BIN
timeline/api/images/bubble-left.png View File


BIN
timeline/api/images/bubble-right-arrow.png View File


BIN
timeline/api/images/bubble-right.png View File


BIN
timeline/api/images/bubble-top-arrow.png View File


BIN
timeline/api/images/bubble-top-left.png View File


BIN
timeline/api/images/bubble-top-right.png View File


BIN
timeline/api/images/bubble-top.png View File


BIN
timeline/api/images/close-button.png View File


BIN
timeline/api/images/copyright-vertical.png View File


BIN
timeline/api/images/copyright.png View File


BIN
timeline/api/images/dark-blue-circle.png View File


BIN
timeline/api/images/dark-green-circle.png View File


BIN
timeline/api/images/dark-red-circle.png View File


BIN
timeline/api/images/dull-blue-circle.png View File


BIN
timeline/api/images/dull-green-circle.png View File


BIN
timeline/api/images/dull-red-circle.png View File


BIN
timeline/api/images/gray-circle.png View File


BIN
timeline/api/images/green-circle.png View File


BIN
timeline/api/images/message-bottom-left.png View File


BIN
timeline/api/images/message-bottom-right.png View File


BIN
timeline/api/images/message-left.png View File


BIN
timeline/api/images/message-right.png View File


BIN
timeline/api/images/message-top-left.png View File


BIN
timeline/api/images/message-top-right.png View File


BIN
timeline/api/images/progress-running.gif View File


BIN
timeline/api/images/red-circle.png View File


BIN
timeline/api/images/top-bubble.png View File


+ 733
- 0
timeline/api/scripts/band.js View File

@@ -0,0 +1,733 @@
/*=================================================
*
* Coding standards:
*
* We aim towards Douglas Crockford's Javascript conventions.
* See: http://javascript.crockford.com/code.html
* See also: http://www.crockford.com/javascript/javascript.html
*
* That said, this JS code was written before some recent JS
* support libraries became widely used or available.
* In particular, the _ character is used to indicate a class function or
* variable that should be considered private to the class.
*
* The code mostly uses accessor methods for getting/setting the private
* class variables.
*
* Over time, we'd like to formalize the convention by using support libraries
* which enforce privacy in objects.
*
* We also want to use jslint: http://www.jslint.com/
*
*
*==================================================
*/



/*==================================================
* Band
*==================================================
*/
Timeline._Band = function(timeline, bandInfo, index) {
// Set up the band's object
// Munge params: If autoWidth is on for the Timeline, then ensure that
// bandInfo.width is an integer
if (timeline.autoWidth && typeof bandInfo.width == 'string') {
bandInfo.width = bandInfo.width.indexOf("%") > -1 ? 0 : parseInt(bandInfo.width);
}

this._timeline = timeline;
this._bandInfo = bandInfo;
this._index = index;
this._locale = ("locale" in bandInfo) ? bandInfo.locale : Timeline.getDefaultLocale();
this._timeZone = ("timeZone" in bandInfo) ? bandInfo.timeZone : 0;
this._labeller = ("labeller" in bandInfo) ? bandInfo.labeller :
(("createLabeller" in timeline.getUnit()) ?
timeline.getUnit().createLabeller(this._locale, this._timeZone) :
new Timeline.GregorianDateLabeller(this._locale, this._timeZone));
this._theme = bandInfo.theme;
this._zoomIndex = ("zoomIndex" in bandInfo) ? bandInfo.zoomIndex : 0;
this._zoomSteps = ("zoomSteps" in bandInfo) ? bandInfo.zoomSteps : null;

this._dragging = false;
this._changing = false;
this._originalScrollSpeed = 5; // pixels
this._scrollSpeed = this._originalScrollSpeed;
this._onScrollListeners = [];
var b = this;
this._syncWithBand = null;
this._syncWithBandHandler = function(band) {
b._onHighlightBandScroll();
};
this._selectorListener = function(band) {
b._onHighlightBandScroll();
};
/*
* Install a textbox to capture keyboard events
*/
var inputDiv = this._timeline.getDocument().createElement("div");
inputDiv.className = "timeline-band-input";
this._timeline.addDiv(inputDiv);
this._keyboardInput = document.createElement("input");
this._keyboardInput.type = "text";
inputDiv.appendChild(this._keyboardInput);
SimileAjax.DOM.registerEventWithObject(this._keyboardInput, "keydown", this, "_onKeyDown");
SimileAjax.DOM.registerEventWithObject(this._keyboardInput, "keyup", this, "_onKeyUp");
/*
* The band's outer most div that slides with respect to the timeline's div
*/
this._div = this._timeline.getDocument().createElement("div");
this._div.id = "timeline-band-" + index;
this._div.className = "timeline-band timeline-band-" + index;
this._timeline.addDiv(this._div);
SimileAjax.DOM.registerEventWithObject(this._div, "mousedown", this, "_onMouseDown");
SimileAjax.DOM.registerEventWithObject(this._div, "mousemove", this, "_onMouseMove");
SimileAjax.DOM.registerEventWithObject(this._div, "mouseup", this, "_onMouseUp");
SimileAjax.DOM.registerEventWithObject(this._div, "mouseout", this, "_onMouseOut");
SimileAjax.DOM.registerEventWithObject(this._div, "dblclick", this, "_onDblClick");
var mouseWheel = this._theme!= null ? this._theme.mouseWheel : 'scroll'; // theme is not always defined
if (mouseWheel === 'zoom' || mouseWheel === 'scroll' || this._zoomSteps) {
// capture mouse scroll
if (SimileAjax.Platform.browser.isFirefox) {
SimileAjax.DOM.registerEventWithObject(this._div, "DOMMouseScroll", this, "_onMouseScroll");
} else {
SimileAjax.DOM.registerEventWithObject(this._div, "mousewheel", this, "_onMouseScroll");
}
}
/*
* The inner div that contains layers
*/
this._innerDiv = this._timeline.getDocument().createElement("div");
this._innerDiv.className = "timeline-band-inner";
this._div.appendChild(this._innerDiv);
/*
* Initialize parts of the band
*/
this._ether = bandInfo.ether;
bandInfo.ether.initialize(this, timeline);
this._etherPainter = bandInfo.etherPainter;
bandInfo.etherPainter.initialize(this, timeline);
this._eventSource = bandInfo.eventSource;
if (this._eventSource) {
this._eventListener = {
onAddMany: function() { b._onAddMany(); },
onClear: function() { b._onClear(); }
}
this._eventSource.addListener(this._eventListener);
}
this._eventPainter = bandInfo.eventPainter;
this._eventTracksNeeded = 0; // set by painter via updateEventTrackInfo
this._eventTrackIncrement = 0;
bandInfo.eventPainter.initialize(this, timeline);
this._decorators = ("decorators" in bandInfo) ? bandInfo.decorators : [];
for (var i = 0; i < this._decorators.length; i++) {
this._decorators[i].initialize(this, timeline);
}
};

Timeline._Band.SCROLL_MULTIPLES = 5;

Timeline._Band.prototype.dispose = function() {
this.closeBubble();
if (this._eventSource) {
this._eventSource.removeListener(this._eventListener);
this._eventListener = null;
this._eventSource = null;
}
this._timeline = null;
this._bandInfo = null;
this._labeller = null;
this._ether = null;
this._etherPainter = null;
this._eventPainter = null;
this._decorators = null;
this._onScrollListeners = null;
this._syncWithBandHandler = null;
this._selectorListener = null;
this._div = null;
this._innerDiv = null;
this._keyboardInput = null;
};

Timeline._Band.prototype.addOnScrollListener = function(listener) {
this._onScrollListeners.push(listener);
};

Timeline._Band.prototype.removeOnScrollListener = function(listener) {
for (var i = 0; i < this._onScrollListeners.length; i++) {
if (this._onScrollListeners[i] == listener) {
this._onScrollListeners.splice(i, 1);
break;
}
}
};

Timeline._Band.prototype.setSyncWithBand = function(band, highlight) {
if (this._syncWithBand) {
this._syncWithBand.removeOnScrollListener(this._syncWithBandHandler);
}
this._syncWithBand = band;
this._syncWithBand.addOnScrollListener(this._syncWithBandHandler);
this._highlight = highlight;
this._positionHighlight();
};

Timeline._Band.prototype.getLocale = function() {
return this._locale;
};

Timeline._Band.prototype.getTimeZone = function() {
return this._timeZone;
};

Timeline._Band.prototype.getLabeller = function() {
return this._labeller;
};

Timeline._Band.prototype.getIndex = function() {
return this._index;
};

Timeline._Band.prototype.getEther = function() {
return this._ether;
};

Timeline._Band.prototype.getEtherPainter = function() {
return this._etherPainter;
};

Timeline._Band.prototype.getEventSource = function() {
return this._eventSource;
};

Timeline._Band.prototype.getEventPainter = function() {
return this._eventPainter;
};

Timeline._Band.prototype.getTimeline = function() {
return this._timeline;
};

// Autowidth support
Timeline._Band.prototype.updateEventTrackInfo = function(tracks, increment) {
this._eventTrackIncrement = increment; // doesn't vary for a specific band

if (tracks > this._eventTracksNeeded) {
this._eventTracksNeeded = tracks;
}
};

// Autowidth support
Timeline._Band.prototype.checkAutoWidth = function() {
// if a new (larger) width is needed by the band
// then: a) updates the band's bandInfo.width
//
// desiredWidth for the band is
// (number of tracks + margin) * track increment
if (! this._timeline.autoWidth) {
return; // early return
}
var overviewBand = this._eventPainter.getType() == 'overview';
var margin = overviewBand ?
this._theme.event.overviewTrack.autoWidthMargin :
this._theme.event.track.autoWidthMargin;
var desiredWidth = Math.ceil((this._eventTracksNeeded + margin) *
this._eventTrackIncrement);
// add offset amount (additional margin)
desiredWidth += overviewBand ? this._theme.event.overviewTrack.offset :
this._theme.event.track.offset;
var bandInfo = this._bandInfo;
if (desiredWidth != bandInfo.width) {
bandInfo.width = desiredWidth;
}
};

Timeline._Band.prototype.layout = function() {
this.paint();
};

Timeline._Band.prototype.paint = function() {
this._etherPainter.paint();
this._paintDecorators();
this._paintEvents();
};

Timeline._Band.prototype.softLayout = function() {
this.softPaint();
};

Timeline._Band.prototype.softPaint = function() {
this._etherPainter.softPaint();
this._softPaintDecorators();
this._softPaintEvents();
};

Timeline._Band.prototype.setBandShiftAndWidth = function(shift, width) {
var inputDiv = this._keyboardInput.parentNode;
var middle = shift + Math.floor(width / 2);
if (this._timeline.isHorizontal()) {
this._div.style.top = shift + "px";
this._div.style.height = width + "px";
inputDiv.style.top = middle + "px";
inputDiv.style.left = "-1em";
} else {
this._div.style.left = shift + "px";
this._div.style.width = width + "px";
inputDiv.style.left = middle + "px";
inputDiv.style.top = "-1em";
}
};

Timeline._Band.prototype.getViewWidth = function() {
if (this._timeline.isHorizontal()) {
return this._div.offsetHeight;
} else {
return this._div.offsetWidth;
}
};

Timeline._Band.prototype.setViewLength = function(length) {
this._viewLength = length;
this._recenterDiv();
this._onChanging();
};

Timeline._Band.prototype.getViewLength = function() {
return this._viewLength;
};

Timeline._Band.prototype.getTotalViewLength = function() {
return Timeline._Band.SCROLL_MULTIPLES * this._viewLength;
};

Timeline._Band.prototype.getViewOffset = function() {
return this._viewOffset;
};

Timeline._Band.prototype.getMinDate = function() {
return this._ether.pixelOffsetToDate(this._viewOffset);
};

Timeline._Band.prototype.getMaxDate = function() {
return this._ether.pixelOffsetToDate(this._viewOffset + Timeline._Band.SCROLL_MULTIPLES * this._viewLength);
};

Timeline._Band.prototype.getMinVisibleDate = function() {
return this._ether.pixelOffsetToDate(0);
};

Timeline._Band.prototype.getMinVisibleDateAfterDelta = function(delta) {
return this._ether.pixelOffsetToDate(delta);
};

Timeline._Band.prototype.getMaxVisibleDate = function() {
// Max date currently visible on band
return this._ether.pixelOffsetToDate(this._viewLength);
};

Timeline._Band.prototype.getMaxVisibleDateAfterDelta = function(delta) {
// Max date visible on band after delta px view change is applied
return this._ether.pixelOffsetToDate(this._viewLength + delta);
};

Timeline._Band.prototype.getCenterVisibleDate = function() {
return this._ether.pixelOffsetToDate(this._viewLength / 2);
};

Timeline._Band.prototype.setMinVisibleDate = function(date) {
if (!this._changing) {
this._moveEther(Math.round(-this._ether.dateToPixelOffset(date)));
}
};

Timeline._Band.prototype.setMaxVisibleDate = function(date) {
if (!this._changing) {
this._moveEther(Math.round(this._viewLength - this._ether.dateToPixelOffset(date)));
}
};

Timeline._Band.prototype.setCenterVisibleDate = function(date) {
if (!this._changing) {
this._moveEther(Math.round(this._viewLength / 2 - this._ether.dateToPixelOffset(date)));
}
};

Timeline._Band.prototype.dateToPixelOffset = function(date) {
return this._ether.dateToPixelOffset(date) - this._viewOffset;
};

Timeline._Band.prototype.pixelOffsetToDate = function(pixels) {
return this._ether.pixelOffsetToDate(pixels + this._viewOffset);
};

Timeline._Band.prototype.createLayerDiv = function(zIndex, className) {
var div = this._timeline.getDocument().createElement("div");
div.className = "timeline-band-layer" + (typeof className == "string" ? (" " + className) : "");
div.style.zIndex = zIndex;
this._innerDiv.appendChild(div);
var innerDiv = this._timeline.getDocument().createElement("div");
innerDiv.className = "timeline-band-layer-inner";
if (SimileAjax.Platform.browser.isIE) {
innerDiv.style.cursor = "move";
} else {
innerDiv.style.cursor = "-moz-grab";
}
div.appendChild(innerDiv);
return innerDiv;
};

Timeline._Band.prototype.removeLayerDiv = function(div) {
this._innerDiv.removeChild(div.parentNode);
};

Timeline._Band.prototype.scrollToCenter = function(date, f) {
var pixelOffset = this._ether.dateToPixelOffset(date);
if (pixelOffset < -this._viewLength / 2) {
this.setCenterVisibleDate(this.pixelOffsetToDate(pixelOffset + this._viewLength));
} else if (pixelOffset > 3 * this._viewLength / 2) {
this.setCenterVisibleDate(this.pixelOffsetToDate(pixelOffset - this._viewLength));
}
this._autoScroll(Math.round(this._viewLength / 2 - this._ether.dateToPixelOffset(date)), f);
};

Timeline._Band.prototype.showBubbleForEvent = function(eventID) {
var evt = this.getEventSource().getEvent(eventID);
if (evt) {
var self = this;
this.scrollToCenter(evt.getStart(), function() {
self._eventPainter.showBubble(evt);
});
}
};

Timeline._Band.prototype.zoom = function(zoomIn, x, y, target) {
if (!this._zoomSteps) {
// zoom disabled
return;
}
// shift the x value by our offset
x += this._viewOffset;

var zoomDate = this._ether.pixelOffsetToDate(x);
var netIntervalChange = this._ether.zoom(zoomIn);
this._etherPainter.zoom(netIntervalChange);

// shift our zoom date to the far left
this._moveEther(Math.round(-this._ether.dateToPixelOffset(zoomDate)));
// then shift it back to where the mouse was
this._moveEther(x);
};

Timeline._Band.prototype._onMouseDown = function(innerFrame, evt, target) {
this.closeBubble();
this._dragging = true;
this._dragX = evt.clientX;
this._dragY = evt.clientY;
};

Timeline._Band.prototype._onMouseMove = function(innerFrame, evt, target) {
if (this._dragging) {
var diffX = evt.clientX - this._dragX;
var diffY = evt.clientY - this._dragY;
this._dragX = evt.clientX;
this._dragY = evt.clientY;
this._moveEther(this._timeline.isHorizontal() ? diffX : diffY);
this._positionHighlight();
}
};

Timeline._Band.prototype._onMouseUp = function(innerFrame, evt, target) {
this._dragging = false;
this._keyboardInput.focus();
};

Timeline._Band.prototype._onMouseOut = function(innerFrame, evt, target) {
var coords = SimileAjax.DOM.getEventRelativeCoordinates(evt, innerFrame);
coords.x += this._viewOffset;
if (coords.x < 0 || coords.x > innerFrame.offsetWidth ||
coords.y < 0 || coords.y > innerFrame.offsetHeight) {
this._dragging = false;
}
};

Timeline._Band.prototype._onMouseScroll = function(innerFrame, evt, target) {
var now = new Date();
now = now.getTime();

if (!this._lastScrollTime || ((now - this._lastScrollTime) > 50)) {
// limit 1 scroll per 200ms due to FF3 sending multiple events back to back
this._lastScrollTime = now;

var delta = 0;
if (evt.wheelDelta) {
delta = evt.wheelDelta/120;
} else if (evt.detail) {
delta = -evt.detail/3;
}
// either scroll or zoom
var mouseWheel = this._theme.mouseWheel;
if (this._zoomSteps || mouseWheel === 'zoom') {
var loc = SimileAjax.DOM.getEventRelativeCoordinates(evt, innerFrame);
if (delta != 0) {
var zoomIn;
if (delta > 0)
zoomIn = true;
if (delta < 0)
zoomIn = false;
// call zoom on the timeline so we could zoom multiple bands if desired
this._timeline.zoom(zoomIn, loc.x, loc.y, innerFrame);
}
}
else if (mouseWheel === 'scroll') {
var move_amt = 50 * (delta < 0 ? -1 : 1);
this._moveEther(move_amt);
}
}

// prevent bubble
if (evt.stopPropagation) {
evt.stopPropagation();
}
evt.cancelBubble = true;

// prevent the default action
if (evt.preventDefault) {
evt.preventDefault();
}
evt.returnValue = false;
};

Timeline._Band.prototype._onDblClick = function(innerFrame, evt, target) {
var coords = SimileAjax.DOM.getEventRelativeCoordinates(evt, innerFrame);
var distance = coords.x - (this._viewLength / 2 - this._viewOffset);
this._autoScroll(-distance);
};

Timeline._Band.prototype._onKeyDown = function(keyboardInput, evt, target) {
if (!this._dragging) {
switch (evt.keyCode) {
case 27: // ESC
break;
case 37: // left arrow
case 38: // up arrow
this._scrollSpeed = Math.min(50, Math.abs(this._scrollSpeed * 1.05));
this._moveEther(this._scrollSpeed);
break;
case 39: // right arrow
case 40: // down arrow
this._scrollSpeed = -Math.min(50, Math.abs(this._scrollSpeed * 1.05));
this._moveEther(this._scrollSpeed);
break;
default:
return true;
}
this.closeBubble();
SimileAjax.DOM.cancelEvent(evt);
return false;
}
return true;
};

Timeline._Band.prototype._onKeyUp = function(keyboardInput, evt, target) {
if (!this._dragging) {
this._scrollSpeed = this._originalScrollSpeed;
switch (evt.keyCode) {
case 35: // end
this.setCenterVisibleDate(this._eventSource.getLatestDate());
break;
case 36: // home
this.setCenterVisibleDate(this._eventSource.getEarliestDate());
break;
case 33: // page up
this._autoScroll(this._timeline.getPixelLength());
break;
case 34: // page down
this._autoScroll(-this._timeline.getPixelLength());
break;
default:
return true;
}
this.closeBubble();
SimileAjax.DOM.cancelEvent(evt);
return false;
}
return true;
};

Timeline._Band.prototype._autoScroll = function(distance, f) {
var b = this;
var a = SimileAjax.Graphics.createAnimation(
function(abs, diff) {
b._moveEther(diff);
},
0,
distance,
1000,
f
);
a.run();
};

Timeline._Band.prototype._moveEther = function(shift) {
this.closeBubble();
// A positive shift means back in time
// Check that we're not moving beyond Timeline's limits
if (!this._timeline.shiftOK(this._index, shift)) {
return; // early return
}

this._viewOffset += shift;
this._ether.shiftPixels(-shift);
if (this._timeline.isHorizontal()) {
this._div.style.left = this._viewOffset + "px";
} else {
this._div.style.top = this._viewOffset + "px";
}
if (this._viewOffset > -this._viewLength * 0.5 ||
this._viewOffset < -this._viewLength * (Timeline._Band.SCROLL_MULTIPLES - 1.5)) {
this._recenterDiv();
} else {
this.softLayout();
}
this._onChanging();
}