Creates a timeline from Zotero items using the Timeline tool from MIT's Simile project. You can create a timeline by clicking the Actions icon in Zotero and then clicking Create Timeline.

This commit is contained in:
Ben Parr 2007-07-31 17:08:12 +00:00
parent d8de14f047
commit 0f5bd0d1cf
11 changed files with 1443 additions and 1 deletions

View File

@ -118,7 +118,8 @@
<menupopup id="zotero-tb-actions-popup" onpopupshowing="document.getElementById('cmd_zotero_reportErrors').setAttribute('disabled', Zotero.getErrors().length == 0)">
<menuitem id="zotero-tb-actions-import" label="&zotero.toolbar.import.label;" oncommand="Zotero_File_Interface.importFile();"/>
<menuitem id="zotero-tb-actions-export" label="&zotero.toolbar.export.label;" oncommand="Zotero_File_Interface.exportFile();"/>
<menuseparator id="zotero-tb-actions-utilities-separator" hidden="true"/>
<menuseparator id="zotero-tb-actions-utilities-separator"/>
<menuitem id="zotero-tb-actions-timeline" label="&zotero.toolbar.timeline.label;" oncommand="window.loadURI('zotero://timeline/')"/>
<menuseparator id="zotero-tb-actions-separator"/>
<menuitem id="zotero-tb-actions-prefs" label="&zotero.toolbar.preferences.label;"
oncommand="window.openDialog('chrome://zotero/content/preferences/preferences.xul', 'zotero-prefs', 'chrome,titlebar,toolbar,' + Zotero.Prefs.get('browser.preferences.instantApply', true) ? 'dialog=no' : 'modal')"/>

View File

@ -0,0 +1,56 @@
/*
***** BEGIN LICENSE BLOCK *****
Copyright (c) 2006 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://chnm.gmu.edu
Licensed under the Educational Community License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.opensource.org/licenses/ecl1.php
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Based on nsChromeExtensionHandler example code by Ed Anuff at
http://kb.mozillazine.org/Dev_:_Extending_the_Chrome_Protocol
***** END LICENSE BLOCK *****
*/
Zotero.Timeline = new function () {
this.generateXMLDetails = generateXMLDetails;
this.generateXMLList = generateXMLList;
function generateXMLDetails(items, dateType) {
var ZU = new Zotero.Utilities();
var escapeXML = ZU.htmlSpecialChars;
var content = '<data>\n';
for each(var arr in items) {
if (arr[dateType]) {
var item = Zotero.Items.get(arr.itemID);
var theDate =(dateType == 'date') ? Zotero.Date.multipartToSQL(arr[dateType]):arr[dateType];
content += '<event start="' + Zotero.Date.sqlToDate(theDate) + '" ';
content += 'title=" ' + escapeXML(arr.title) + '" ';
content += 'icon="' + item.getImageSrc() + '" ';
content += 'color="black">';
content += 'zotero://select/item/'+arr.itemID;
content += '</event>\n';
}
}
content += '</data>';
return content;
}
function generateXMLList(items) {
}
}

View File

@ -0,0 +1,36 @@
general.title = Zotero Timeline
general.filter = Filter:
general.highlight = Highlight:
general.clearAll = Clear All
general.jumpToYear = Jump to Year:
general.firstBand = First Band:
general.secondBand = Second Band:
general.thirdBand = Third Band:
general.dateType = Date Type:
general.timelineHeight = Timeline Height:
general.go = Go...
general.fitToScreen = Fit to Screen
interval.day = Day
interval.month = Month
interval.year = Year
interval.decade = Decade
interval.century = Century
interval.millennium = Millennium
dateType.published = Date Published
dateType.added = Date Added
dateType.modified = Date Modified
shortName.january = Jan
shortName.february = Feb
shortName.march = Mar
shortName.april = Apr
shortName.may = May
shortName.june = Jun
shortName.july = Jul
shortName.august = Aug
shortName.september = Sep
shortName.october = Oct
shortName.november = Nov
shortName.december = Dec

View File

@ -62,6 +62,7 @@
<!ENTITY zotero.toolbar.actions.label "Actions">
<!ENTITY zotero.toolbar.import.label "Import...">
<!ENTITY zotero.toolbar.export.label "Export Library...">
<!ENTITY zotero.toolbar.timeline.label "Create Timeline">
<!ENTITY zotero.toolbar.preferences.label "Preferences...">
<!ENTITY zotero.toolbar.documentation.label "Documentation">
<!ENTITY zotero.toolbar.about.label "About Zotero">

View File

@ -0,0 +1,172 @@
.timeline-ether-marker-bottom {
width: 5em;
height: 1.5em;
border-left: 1px solid #aaa;
padding-left: 2px;
color: #aaa;
}
.timeline-ether-marker-bottom-emphasized {
width: 5em;
height: 2em;
border-left: 1px solid #aaa;
padding-left: 2px;
color: black;
}
.timeline-ether-marker-top {
width: 5em;
height: 1.5em;
border-left: 1px solid #aaa;
padding-left: 2px;
color: #aaa;
}
.timeline-ether-marker-top-emphasized {
width: 5em;
height: 2em;
border-left: 1px solid #aaa;
padding-left: 2px;
color: black;
}
.timeline-ether-marker-right {
width: 5em;
height: 1.5em;
border-top: 1px solid #aaa;
padding-top: 2px;
color: #aaa;
}
.timeline-ether-marker-right-emphasized {
width: 7em;
height: 1.5em;
border-top: 1px solid #aaa;
padding-top: 2px;
color: black;
}
.timeline-ether-marker-left {
width: 5em;
height: 1.5em;
border-top: 1px solid #aaa;
padding-top: 2px;
color: #aaa;
}
.timeline-ether-marker-left-emphasized {
width: 7em;
height: 1.5em;
border-top: 1px solid #aaa;
padding-top: 2px;
color: black;
}
.timeline-duration-event {
position: absolute;
overflow: hidden;
border: 1px solid blue;
}
.timeline-instant-event2 {
position: absolute;
overflow: hidden;
border-left: 1px solid blue;
padding-left: 2px;
}
.timeline-instant-event {
position: absolute;
overflow: hidden;
}
.timeline-event-bubble-title {
font-weight: bold;
border-bottom: 1px solid #888;
margin-bottom: 0.5em;
}
.timeline-event-bubble-body {
}
.timeline-event-bubble-wiki {
margin: 0.5em;
text-align: right;
color: #A0A040;
}
.timeline-event-bubble-wiki a {
color: #A0A040;
}
.timeline-event-bubble-time {
color: #aaa;
}
.timeline-event-bubble-image {
float: right;
padding-left: 5px;
padding-bottom: 5px;
}.timeline-container {
position: relative;
overflow: hidden;
}
.timeline-copyright {
position: absolute;
bottom: 0px;
left: 0px;
z-index: 1000;
cursor: pointer;
}
.timeline-message-container {
position: absolute;
top: 30%;
left: 35%;
right: 35%;
z-index: 1000;
display: none;
}
.timeline-message {
font-size: 120%;
font-weight: bold;
text-align: center;
}
.timeline-message img {
vertical-align: middle;
}
.timeline-band {
position: absolute;
background: #eee;
z-index: 10;
}
.timeline-band-inner {
position: relative;
width: 100%;
height: 100%;
}
.timeline-band-input {
position: absolute;
width: 1em;
height: 1em;
overflow: hidden;
z-index: 0;
}
.timeline-band-input input{
width: 0;
}
.timeline-band-layer {
position: absolute;
width: 100%;
height: 100%;
}
.timeline-band-layer-inner {
position: relative;
width: 100%;
height: 100%;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,230 @@
/*==================================================
* Timeline API
*
* This file will load all the Javascript files
* necessary to make the standard timeline work.
* It also detects the default locale.
*
* Include this file in your HTML file as follows:
*
* <script src="http://simile.mit.edu/timeline/api/scripts/timeline-api.js" type="text/javascript"></script>
*
*==================================================
*/
var Timeline = new Object();
Timeline.Platform = new Object();
/*
HACK: We need these 2 things here because we cannot simply append
a <script> element containing code that accesses Timeline.Platform
to initialize it because IE executes that <script> code first
before it loads timeline.js and util/platform.js.
*/
(function() {
var bundle = true;
var javascriptFiles = [
"timeline.js",
"util/platform.js",
"util/debug.js",
"util/xmlhttp.js",
"util/dom.js",
"util/graphics.js",
"util/date-time.js",
"util/data-structure.js",
"util/html.js",
"units.js",
"themes.js",
"ethers.js",
"ether-painters.js",
"labellers.js",
"sources.js",
"layouts.js",
"painters.js",
"decorators.js"
];
var cssFiles = [
"timeline.css",
"ethers.css",
"events.css"
];
// ISO-639 language codes, ISO-3166 country codes (2 characters)
var supportedLocales = [
"cs", // Czech
"de", // German
"en", // English
"es", // Spanish
"fr", // French
"it", // Italian
"ru", // Russian
"se", // Swedish
"vi", // Vietnamese
"zh" // Chinese
];
try {
var desiredLocales = [ "en" ];
var defaultServerLocale = "en";
var parseURLParameters = function(parameters) {
var params = parameters.split("&");
for (var p = 0; p < params.length; p++) {
var pair = params[p].split("=");
if (pair[0] == "locales") {
desiredLocales = desiredLocales.concat(pair[1].split(","));
} else if (pair[0] == "defaultLocale") {
defaultServerLocale = pair[1];
} else if (pair[0] == "bundle") {
bundle = pair[1] != "false";
}
}
};
(function() {
if (typeof Timeline_urlPrefix == "string") {
Timeline.urlPrefix = Timeline_urlPrefix;
if (typeof Timeline_parameters == "string") {
parseURLParameters(Timeline_parameters);
}
} else {
var heads = document.documentElement.getElementsByTagName("head");
for (var h = 0; h < heads.length; h++) {
var scripts = heads[h].getElementsByTagName("script");
for (var s = 0; s < scripts.length; s++) {
var url = scripts[s].src;
var i = url.indexOf("timeline-api.js");
if (i >= 0) {
Timeline.urlPrefix = url.substr(0, i);
var q = url.indexOf("?");
if (q > 0) {
parseURLParameters(url.substr(q + 1));
}
return;
}
}
}
throw new Error("Failed to derive URL prefix for Timeline API code files");
}
})();
var includeJavascriptFiles;
var includeCssFiles;
if ("SimileAjax" in window) {
includeJavascriptFiles = function(urlPrefix, filenames) {
SimileAjax.includeJavascriptFiles(document, urlPrefix, filenames);
}
includeCssFiles = function(urlPrefix, filenames) {
SimileAjax.includeCssFiles(document, urlPrefix, filenames);
}
} else {
var getHead = function() {
return document.getElementsByTagName("head")[0];
};
var includeJavascriptFile = function(url) {
if (document.body == null) {
try {
document.write("<script src='" + url + "' type='text/javascript'></script>");
return;
} catch (e) {
// fall through
}
}
var script = document.createElement("script");
script.type = "text/javascript";
script.language = "JavaScript";
script.src = url;
getHead().appendChild(script);
};
var includeCssFile = function(url) {
if (document.body == null) {
try {
document.write("<link rel='stylesheet' href='" + url + "' type='text/css'/>");
return;
} catch (e) {
// fall through
}
}
var link = document.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.setAttribute("href", url);
getHead().appendChild(link);
}
includeJavascriptFiles = function(urlPrefix, filenames) {
for (var i = 0; i < filenames.length; i++) {
includeJavascriptFile(urlPrefix + filenames[i]);
}
};
includeCssFiles = function(urlPrefix, filenames) {
for (var i = 0; i < filenames.length; i++) {
includeCssFile(urlPrefix + filenames[i]);
}
};
}
/*
* Include non-localized files
*/
if (bundle) {
includeJavascriptFiles(Timeline.urlPrefix, [ "bundle.js" ]);
includeCssFiles(Timeline.urlPrefix, [ "bundle.css" ]);
} else {
includeJavascriptFiles(Timeline.urlPrefix + "scripts/", javascriptFiles);
includeCssFiles(Timeline.urlPrefix + "styles/", cssFiles);
}
/*
* Include localized files
*/
var loadLocale = [];
loadLocale[defaultServerLocale] = true;
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;
}
for (var l = 0; l < desiredLocales.length; l++) {
tryLocale(desiredLocales[l]);
}
var defaultClientLocale = defaultServerLocale;
var defaultClientLocales = ("language" in navigator ? navigator.language : navigator.browserLanguage).split(";");
for (var l = 0; l < defaultClientLocales.length; l++) {
var locale = tryLocale(defaultClientLocales[l]);
if (locale != null) {
defaultClientLocale = locale;
break;
}
}
Timeline.Platform.serverLocale = defaultServerLocale;
Timeline.Platform.clientLocale = defaultClientLocale;
} catch (e) {
alert(e);
}
})();

View File

@ -0,0 +1,88 @@
<!DOCTYPE html SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type='text/css'>
BODY {font-family: sans-serif;
font-size: 14px;}
.timeline {
margin: 0px;
padding: 0px;
font-size: 11px;
}
</style>
<script src="chrome://zotero/skin/timeline/timelineControls.js" type="text/javascript"></script>
<script src="chrome://zotero/skin/timeline/timeline-api.js" type="text/javascript"></script>
<script type="text/javascript">
var tl;
function onLoad(a, b, c, date) {
var eventSource = new Timeline.DefaultEventSource();
var theme = Timeline.ClassicTheme.create();
theme.event.label.width = 175;
date = createDate(date);
var bandInfos = [
Timeline.createBandInfo({
eventSource: eventSource,
date: date,
width: "70%",
intervalUnit: a,
intervalPixels: 100,
theme: theme
}),
Timeline.createBandInfo({
showEventText: false,
trackHeight: 0.5,
trackGap: 0.2,
eventSource: eventSource,
date: date,
width: "25%",
intervalUnit: b,
intervalPixels: 200,
theme: theme
}),
Timeline.createBandInfo({
showEventText: false,
trackHeight: 0.5,
trackGap: 0.2,
eventSource: eventSource,
date: date,
width: "5%",
intervalUnit: c,
intervalPixels: 200,
theme: theme
})
];
bandInfos[1].syncWith = 0;
bandInfos[1].highlight = true;
bandInfos[1].eventPainter.setLayout(bandInfos[0].eventPainter.getLayout());
bandInfos[2].syncWith = 0;
bandInfos[2].highlight = true;
tl = Timeline.create(document.getElementById("my-timeline"), bandInfos);
Timeline.loadXML("zotero://timeline/data/", function(xml, url) { eventSource.loadXML(xml, url); });
setupFilterHighlightControls(document.getElementById("my-timeline-controls"), tl, [0,1,2], theme);
setupOtherControls(document.getElementById("my-other-controls"), tl, document.URL);
}
function onResize() {
var curDate = tl.getBand(0).getCenterVisibleDate().toString();
tl.layout();
centerTimeline(curDate);
}
Timeline.DurationEventPainter.prototype._showBubble = function(x, y, evt) {
window.location=evt.getDescription();
}
document.write("<title>"+localeHash["general.title"]+"</title>");
</script>
</head>
<body onload="onLoad();" onresize="onResize()">
<script type="text/javascript">document.write(getTimeline());</script>
<div class="controls" id="my-timeline-controls"></div><br/>
<div class="controls" id="my-other-controls"></div>
</body>
</html>

View File

@ -0,0 +1,405 @@
var localeHash = getLocaleHash();
function getLocaleHash() {
var localeHash = new Object();
var content = getContentsFromURL("chrome://zotero/locale/timeline.properties");
var m;
while(m = /^[\S]+(?=\s*=)/gm.exec(content)) {
localeHash[m] = /=[^\n]+/g.exec(content).toString().replace(/=\s*/,'');;
}
return localeHash;
}
function getContentsFromURL(url) {
var xmlhttp = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance();
xmlhttp.open('GET', url, false);
xmlhttp.send(null);
return xmlhttp.responseText;
}
function getTimeline() {
var tt = getHeight();
tt -= 180;
if (tt < 100) {
tt = 100;
}
return '<div class="timeline" id="my-timeline" style="height: ' + tt + 'px; border: 1px solid #aaa"></div>';
}
function getHeight() {
var temp = document.documentElement.clientHeight;
if(temp && temp > 0) {
return temp;
}
else {
temp=document.body.clientHeight;
if(temp && temp > 0) {
return temp;
}
}
return 0;
}
function doReturn(e)
{
if(e.which) {
if(e.which == '13'){
checkDate(document.getElementById('jumpYear').value);
}
}
}
function getMonthNum(month) {
var months = new Array('jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec');
var num = months.indexOf(month.toLowerCase());
if(num<0){
num = 0;
}
return num;
}
function createDate(date){
date = date.split('.');
var theDate = new Date();
theDate.setMonth(getMonthNum(date[0]));
theDate.setDate(date[1]);
theDate.setFullYear(date[2]);
return theDate;
}
function getTimelineDate(timeline){
var timelineDate = timeline.getBand(0).getCenterVisibleDate().toString();
var dateParts = timelineDate.split(' ');
timelineDate = dateParts[1] + '.' + dateParts[2] + '.' + dateParts[3];
return timelineDate;
}
function checkDate(date) {
var arr = new Array();
var i = 0;
date = date.replace(/[\s|.]/g,'');
//check to see if the year is B.C.
var bc = false;
if (date.substr(date.length - 2).toLowerCase() == 'bc') {
bc = true;
date = date.substr(0, date.length - 2);
}
if(/\D/.test(date)) {
return false;
}
if (bc) {
centerTimeline(date + ' BC');
}
else {
centerTimeline(date);
}
}
function changeBand(band, intervals, date, url, selectedIndex) {
var values = new Array('d', 'm', 'y', 'e', 'c', 'i');
var temp = url.split('/');
var newIntervals = '';
for (var i = 0; i < intervals.length; i++) {
if (i == band) {
newIntervals += values[selectedIndex];
}
else {
newIntervals += intervals[i];
}
}
temp[3] = newIntervals;
temp[4] = date;
window.location = temp.join('/');
}
function changeDateType(url, intervals, values, date, seletedIndex) {
var temp = url.split('/');
temp[3] = intervals;
temp[4] = date;
temp[5] = values[seletedIndex];
window.location = temp.join('/');
}
function createOption(t, selected) {
option = document.createElement("option");
if (selected) {
option.selected = "true";
}
text = document.createTextNode(t);
option.setAttribute("value", t);
option.appendChild(text);
return option;
}
function getFull(a) {
switch (a) {
case 'd':
return localeHash["interval.day"];
case 'm':
return localeHash["interval.month"];
case 'y':
return localeHash["interval.year"];
case 'e':
return localeHash["interval.decade"];
case 'c':
return localeHash["interval.century"];
case 'i':
return localeHash["interval.millennium"];
default:
return false;
}
}
function setupOtherControls(div, timeline, url) {
var table = document.createElement("table");
// url= zotero://timeline/intervals/timelineDate/dateType/type/ids/
var parts = url.split('/');
var intervals = parts[3];
if (intervals.length < 3) {
intervals += "mye".substr(intervals.length);
}
var tr = table.insertRow(0);
var td = tr.insertCell(0);
td.innerHTML = localeHash["general.jumpToYear"];
td = tr.insertCell(tr.cells.length);
td.innerHTML = localeHash["general.firstBand"];
td = tr.insertCell(tr.cells.length);
td.innerHTML = localeHash["general.secondBand"];;
td = tr.insertCell(tr.cells.length);
td.innerHTML = localeHash["general.thirdBand"];;
td = tr.insertCell(tr.cells.length);
td.innerHTML = localeHash["general.dateType"];;
td = tr.insertCell(tr.cells.length);
td.innerHTML = localeHash["general.timelineHeight"];;
tr = table.insertRow(1);
tr.style.verticalAlign = "top";
td = tr.insertCell(0);
var input = document.createElement("input");
input.type = "text";
input.size = "15";
input.id="jumpYear";
input.onkeypress=doReturn;
td.appendChild(input);
var options = new Array(localeHash["interval.day"], localeHash["interval.month"], localeHash["interval.year"],
localeHash["interval.decade"], localeHash["interval.century"], localeHash["interval.millennium"]);
var selected = '';
var theSelects = new Array();
td = tr.insertCell(tr.cells.length);
var select1 = document.createElement("select");
selected = getFull(intervals[0]);
for (var i = 0; i < options.length; i++) {
select1.appendChild(createOption(options[i],(options[i] == selected)));
}
select1.onchange = function () {
changeBand(0, intervals, getTimelineDate(timeline), url, table.rows[1].cells[1].firstChild.selectedIndex);
};
td.appendChild(select1);
td = tr.insertCell(tr.cells.length);
var select2 = document.createElement("select");
selected = getFull(intervals[1]);
for (var i = 0; i < options.length; i++) {
select2.appendChild(createOption(options[i],(options[i] == selected)));
}
select2.onchange = function () {
changeBand(1, intervals, getTimelineDate(timeline), url, table.rows[1].cells[2].firstChild.selectedIndex);
};
td.appendChild(select2);
td = tr.insertCell(tr.cells.length);
var select3 = document.createElement("select");
selected = getFull(intervals[2]);
for (var i = 0; i < options.length; i++) {
select3.appendChild(createOption(options[i],(options[i] == selected)));
}
select3.onchange = function () {
changeBand(2, intervals, getTimelineDate(timeline), url, table.rows[1].cells[3].firstChild.selectedIndex);
};
td.appendChild(select3);
td = tr.insertCell(tr.cells.length);
options = new Array(localeHash["dateType.published"], localeHash["dateType.added"], localeHash["dateType.modified"]);
var values = new Array('date', 'dateAdded', 'dateModified');
var select4 = document.createElement("select");
selected = 0;
if (parts[5]) {
selected = values.indexOf(parts[5]);
}
if (selected < 0) {
selected = 0;
}
for (var i = 0; i < options.length; i++) {
select4.appendChild(createOption(options[i],(i == selected)));
}
select4.onchange = function () {
changeDateType(url, intervals, values, getTimelineDate(timeline), table.rows[1].cells[4].firstChild.selectedIndex);
};
td.appendChild(select4);
td = tr.insertCell(tr.cells.length);
var fitToScreen = document.createElement("button");
fitToScreen.innerHTML = localeHash["general.fitToScreen"];
Timeline.DOM.registerEvent(fitToScreen, "click", function () {
var temp = url.split('/');
temp[3] = intervals;
temp[4] = getTimelineDate(timeline);
window.location = temp.join('/');
});
td.appendChild(fitToScreen);
tr = table.insertRow(2);
td = tr.insertCell(0);
var button = document.createElement("button");
button.innerHTML = localeHash["general.go"];
Timeline.DOM.registerEvent(button, "click", function () {
checkDate(table.rows[1].cells[0].firstChild.value);
});
td.appendChild(button);
div.appendChild(table);
}
/*
Everything below is from http://simile.mit.edu/timeline/examples/examples.js
*/
function centerTimeline(date) {
tl.getBand(0).setCenterVisibleDate(Timeline.DateTime.parseGregorianDateTime(date));
}
function setupFilterHighlightControls(div, timeline, bandIndices, theme) {
var table = document.createElement("table");
var tr = table.insertRow(0);
var td = tr.insertCell(0);
td.innerHTML = localeHash["general.filter"];
td = tr.insertCell(1);
td.innerHTML = localeHash["general.highlight"];
var handler = function (elmt, evt, target) {
onKeyPress(timeline, bandIndices, table);
};
tr = table.insertRow(1);
tr.style.verticalAlign = "top";
td = tr.insertCell(0);
input = document.createElement("input");
input.type = "text";
input.size = "18";
Timeline.DOM.registerEvent(input, "keypress", handler);
td.appendChild(input);
for (var i = 0; i < theme.event.highlightColors.length; i++) {
td = tr.insertCell(i + 1);
input = document.createElement("input");
input.type = "text";
Timeline.DOM.registerEvent(input, "keypress", handler);
td.appendChild(input);
input.size = "15";
var divColor = document.createElement("div");
divColor.style.height = "0.5em";
divColor.style.background = theme.event.highlightColors[i];
td.appendChild(divColor);
}
td = tr.insertCell(tr.cells.length);
button = document.createElement("button");
button.innerHTML = localeHash["general.clearAll"];
Timeline.DOM.registerEvent(button, "click", function () {
clearAll(timeline, bandIndices, table);
});
td.appendChild(button);
div.appendChild(table);
}
var timerID = null;
function onKeyPress(timeline, bandIndices, table) {
if (timerID != null) {
window.clearTimeout(timerID);
}
timerID = window.setTimeout(function () {
performFiltering(timeline, bandIndices, table);
}, 300);
}
function cleanString(s) {
return s.replace(/^\s + /, '').replace(/\s + $/, '');
}
function performFiltering(timeline, bandIndices, table) {
timerID = null;
var tr = table.rows[1];
var text = cleanString(tr.cells[0].firstChild.value);
var filterMatcher = null;
if (text.length > 0) {
var regex = new RegExp(text, "i");
filterMatcher = function (evt) {
return regex.test(evt.getText()) || regex.test(evt.getDescription());
};
}
var regexes = [];
var hasHighlights = false;
for (var x = 1; x < tr.cells.length - 1; x++) {
var input = tr.cells[x].firstChild;
var text2 = cleanString(input.value);
if (text2.length > 0) {
hasHighlights = true;
regexes.push(new RegExp(text2, "i"));
} else {
regexes.push(null);
}
}
var highlightMatcher = hasHighlights ? function (evt) {
var text = evt.getText();
var description = evt.getDescription();
for (var x = 0; x < regexes.length; x++) {
var regex = regexes[x];
if (regex != null && (regex.test(text) || regex.test(description))) {
return x;
}
}
return - 1;
} : null;
for (var i = 0; i < bandIndices.length; i++) {
var bandIndex = bandIndices[i];
timeline.getBand(bandIndex).getEventPainter().setFilterMatcher(filterMatcher);
timeline.getBand(bandIndex).getEventPainter().setHighlightMatcher(highlightMatcher);
}
timeline.paint();
}
function clearAll(timeline, bandIndices, table) {
var tr = table.rows[1];
for (var x = 0; x < tr.cells.length - 1; x++) {
tr.cells[x].firstChild.value = "";
}
for (var i = 0; i < bandIndices.length; i++) {
var bandIndex = bandIndices[i];
timeline.getBand(bandIndex).getEventPainter().setFilterMatcher(null);
timeline.getBand(bandIndex).getEventPainter().setHighlightMatcher(null);
}
timeline.paint();
}

View File

@ -222,11 +222,206 @@ function ChromeExtensionHandler() {
return extChannel;
}
};
var TimelineExtension = new function(){
this.newChannel = newChannel;
function getInterval(a){
switch (a){
case 'd':
return 'Timeline.DateTime.DAY';
case 'm':
return 'Timeline.DateTime.MONTH';
case 'y':
return 'Timeline.DateTime.YEAR';
case 'e':
return 'Timeline.DateTime.DECADE';
case 'c':
return 'Timeline.DateTime.CENTURY';
case 'i':
return 'Timeline.DateTime.MILLENNIUM';
default:
return false;
}
}
/*
zotero://timeline/intervals/timelineDate/dateType/type/ids/ ----->creates html for timeline
zotero://timeline/ ------> minimum needed (defaults: intervals = month, year, decade |
timelineDate = today's date | dateType = date | type = library)
zotero://timeline/data/dateType/type/ids ----->creates XML
*/
function newChannel(uri) {
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var Zotero = Components.classes["@zotero.org/Zotero;1"]
.getService(Components.interfaces.nsISupports)
.wrappedJSObject;
generateContent:try {
var mimeType, content = '';
var [path, queryString] = uri.path.substr(1).split('?');
var pathParts = path.split('/');
if (pathParts[0] != 'data') {
//creates HTML file
var intervals = pathParts[0];
var timelineDate = pathParts[1];
content = Zotero.File.getContentsFromURL('chrome://zotero/skin/timeline/timeline.html');
mimeType = 'text/html';
var theTemp = 'Timeline.loadXML("zotero://timeline/data/';
if(!timelineDate){
timelineDate=Date();
var dateParts=timelineDate.toString().split(' ');
timelineDate=dateParts[1]+'.'+dateParts[2]+'.'+dateParts[3];
}
else {
//passes information (dateType,type,ids) for when the XML is created
content = content.replace(theTemp, theTemp + pathParts.slice(2).join('/'));
}
//sets the intervals of the timeline bands
theTemp = '<body onload="onLoad(';
var a = (getInterval(intervals[0])) ? getInterval(intervals[0]) : 'Timeline.DateTime.MONTH';
var b = (getInterval(intervals[1])) ? getInterval(intervals[1]) : 'Timeline.DateTime.YEAR';
var c = (getInterval(intervals[2])) ? getInterval(intervals[2]) : 'Timeline.DateTime.DECADE';
content = content.replace(theTemp, theTemp + a + ',' + b + ',' + c + ',\'' + timelineDate + '\'');
var uri_str = 'data:' + (mimeType ? mimeType + ',' : '') + encodeURIComponent(content);
var ext_uri = ioService.newURI(uri_str, null, null);
var extChannel = ioService.newChannelFromURI(ext_uri);
return extChannel;
}
else {
var [data, dateType, type, ids] = pathParts;
}
//creates XML file
switch (type){
case 'collection':
var results = Zotero.getItems(ids);
break;
case 'search':
var s = new Zotero.Search(ids);
var ids = s.search();
break;
case 'items':
case 'item':
var ids = ids.split('-');
break;
default:
var type = 'library';
var s = new Zotero.Search();
s.addCondition('noChildren', 'true');
var ids = s.search();
}
if (!results) {
var results = Zotero.Items.get(ids);
}
var items = [];
// Only include parent items
for (var i = 0; i < results.length; i++) {
if (!results[i].getSource()) {
items.push(results[i]);
}
}
if (!items) {
mimeType = 'text/html';
content = 'Invalid ID';
break generateContent;
}
// Convert item objects to export arrays
for (var i = 0; i < items.length; i++) {
items[i] = items[i].toArray();
}
mimeType = 'application/xml';
//default dateType = date (publication date)
if (!dateType) {
dateType = 'date';
}
content = Zotero.Timeline.generateXMLDetails(items, dateType);
}
catch (e){
Zotero.debug(e);
throw (e);
}
var uri_str = 'data:' + (mimeType ? mimeType + ',' : '') + encodeURIComponent(content);
var ext_uri = ioService.newURI(uri_str, null, null);
var extChannel = ioService.newChannelFromURI(ext_uri);
return extChannel;
}
};
/*
zotero://select/type/id
*/
var SelectExtension = new function(){
this.newChannel = newChannel;
function newChannel(uri) {
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var Zotero = Components.classes["@zotero.org/Zotero;1"]
.getService(Components.interfaces.nsISupports)
.wrappedJSObject;
generateContent:try {
var mimeType, content = '';
var [path, queryString] = uri.path.substr(1).split('?');
var [type, id] = path.split('/');
//currently only able to select one item
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow(null);
if(!win.ZoteroPane.isShowing()){
win.ZoteroPane.toggleDisplay();
}
win.ZoteroPane.selectItem(id);
}
catch (e){
Zotero.debug(e);
throw (e);
}
}
};
var ReportExtensionSpec = ZOTERO_SCHEME + "://report"
ReportExtensionSpec = ReportExtensionSpec.toLowerCase();
this._extensions[ReportExtensionSpec] = ReportExtension;
var TimelineExtensionSpec = ZOTERO_SCHEME + "://timeline"
TimelineExtensionSpec = TimelineExtensionSpec.toLowerCase();
this._extensions[TimelineExtensionSpec] = TimelineExtension;
var SelectExtensionSpec = ZOTERO_SCHEME + "://select"
SelectExtensionSpec = SelectExtensionSpec.toLowerCase();
this._extensions[SelectExtensionSpec] = SelectExtension;
}

View File

@ -69,6 +69,10 @@ Cc["@mozilla.org/moz/jssubscript-loader;1"]
Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://zotero/content/xpcom/report.js");
Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://zotero/content/xpcom/timeline.js");
Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader)