Mercurial > hg > LGMap
diff geotemco/lib/simile/timeline/scripts/sources.js @ 0:57bde4830927
first commit
author | Zoe Hong <zhong@mpiwg-berlin.mpg.de> |
---|---|
date | Tue, 24 Mar 2015 11:37:17 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/geotemco/lib/simile/timeline/scripts/sources.js Tue Mar 24 11:37:17 2015 +0100 @@ -0,0 +1,567 @@ +/*================================================== + * Default Event Source + *================================================== + */ + + +Timeline.DefaultEventSource = function(eventIndex) { + this._events = (eventIndex instanceof Object) ? eventIndex : new SimileAjax.EventIndex(); + this._listeners = []; +}; + +Timeline.DefaultEventSource.prototype.addListener = function(listener) { + this._listeners.push(listener); +}; + +Timeline.DefaultEventSource.prototype.removeListener = function(listener) { + for (var i = 0; i < this._listeners.length; i++) { + if (this._listeners[i] == listener) { + this._listeners.splice(i, 1); + break; + } + } +}; + +Timeline.DefaultEventSource.prototype.loadXML = function(xml, url) { + var base = this._getBaseURL(url); + + var wikiURL = xml.documentElement.getAttribute("wiki-url"); + var wikiSection = xml.documentElement.getAttribute("wiki-section"); + + var dateTimeFormat = xml.documentElement.getAttribute("date-time-format"); + var parseDateTimeFunction = this._events.getUnit().getParser(dateTimeFormat); + + var node = xml.documentElement.firstChild; + var added = false; + while (node != null) { + if (node.nodeType == 1) { + var description = ""; + if (node.firstChild != null && node.firstChild.nodeType == 3) { + description = node.firstChild.nodeValue; + } + // instant event: default is true. Or use values from isDuration or durationEvent + var instant = (node.getAttribute("isDuration") === null && + node.getAttribute("durationEvent") === null) || + node.getAttribute("isDuration") == "false" || + node.getAttribute("durationEvent") == "false"; + + var evt = new Timeline.DefaultEventSource.Event( { + id: node.getAttribute("id"), + start: parseDateTimeFunction(node.getAttribute("start")), + end: parseDateTimeFunction(node.getAttribute("end")), + latestStart: parseDateTimeFunction(node.getAttribute("latestStart")), + earliestEnd: parseDateTimeFunction(node.getAttribute("earliestEnd")), + instant: instant, + text: node.getAttribute("title"), + description: description, + image: this._resolveRelativeURL(node.getAttribute("image"), base), + link: this._resolveRelativeURL(node.getAttribute("link") , base), + icon: this._resolveRelativeURL(node.getAttribute("icon") , base), + color: node.getAttribute("color"), + textColor: node.getAttribute("textColor"), + hoverText: node.getAttribute("hoverText"), + classname: node.getAttribute("classname"), + tapeImage: node.getAttribute("tapeImage"), + tapeRepeat: node.getAttribute("tapeRepeat"), + caption: node.getAttribute("caption"), + eventID: node.getAttribute("eventID"), + trackNum: node.getAttribute("trackNum") + }); + + evt._node = node; + evt.getProperty = function(name) { + return this._node.getAttribute(name); + }; + evt.setWikiInfo(wikiURL, wikiSection); + + this._events.add(evt); + + added = true; + } + node = node.nextSibling; + } + + if (added) { + this._fire("onAddMany", []); + } +}; + + +Timeline.DefaultEventSource.prototype.loadJSON = function(data, url) { + var base = this._getBaseURL(url); + var added = false; + if (data && data.events){ + var wikiURL = ("wikiURL" in data) ? data.wikiURL : null; + var wikiSection = ("wikiSection" in data) ? data.wikiSection : null; + + var dateTimeFormat = ("dateTimeFormat" in data) ? data.dateTimeFormat : null; + var parseDateTimeFunction = this._events.getUnit().getParser(dateTimeFormat); + + for (var i=0; i < data.events.length; i++){ + var event = data.events[i]; + // Fixing issue 33: + // instant event: default (for JSON only) is false. Or use values from isDuration or durationEvent + // isDuration was negated (see issue 33, so keep that interpretation + var instant = event.isDuration || (event.durationEvent != null && !event.durationEvent); + + var evt = new Timeline.DefaultEventSource.Event({ + id: ("id" in event) ? event.id : undefined, + start: parseDateTimeFunction(event.start), + end: parseDateTimeFunction(event.end), + latestStart: parseDateTimeFunction(event.latestStart), + earliestEnd: parseDateTimeFunction(event.earliestEnd), + instant: instant, + text: event.title, + description: event.description, + image: this._resolveRelativeURL(event.image, base), + link: this._resolveRelativeURL(event.link , base), + icon: this._resolveRelativeURL(event.icon , base), + color: event.color, + textColor: event.textColor, + hoverText: event.hoverText, + classname: event.classname, + tapeImage: event.tapeImage, + tapeRepeat: event.tapeRepeat, + caption: event.caption, + eventID: event.eventID, + trackNum: event.trackNum + }); + evt._obj = event; + evt.getProperty = function(name) { + return this._obj[name]; + }; + evt.setWikiInfo(wikiURL, wikiSection); + + this._events.add(evt); + added = true; + } + } + + if (added) { + this._fire("onAddMany", []); + } +}; + +/* + * Contributed by Morten Frederiksen, http://www.wasab.dk/morten/ + */ +Timeline.DefaultEventSource.prototype.loadSPARQL = function(xml, url) { + var base = this._getBaseURL(url); + + var dateTimeFormat = 'iso8601'; + var parseDateTimeFunction = this._events.getUnit().getParser(dateTimeFormat); + + if (xml == null) { + return; + } + + /* + * Find <results> tag + */ + var node = xml.documentElement.firstChild; + while (node != null && (node.nodeType != 1 || node.nodeName != 'results')) { + node = node.nextSibling; + } + + var wikiURL = null; + var wikiSection = null; + if (node != null) { + wikiURL = node.getAttribute("wiki-url"); + wikiSection = node.getAttribute("wiki-section"); + + node = node.firstChild; + } + + var added = false; + while (node != null) { + if (node.nodeType == 1) { + var bindings = { }; + var binding = node.firstChild; + while (binding != null) { + if (binding.nodeType == 1 && + binding.firstChild != null && + binding.firstChild.nodeType == 1 && + binding.firstChild.firstChild != null && + binding.firstChild.firstChild.nodeType == 3) { + bindings[binding.getAttribute('name')] = binding.firstChild.firstChild.nodeValue; + } + binding = binding.nextSibling; + } + + if (bindings["start"] == null && bindings["date"] != null) { + bindings["start"] = bindings["date"]; + } + + // instant event: default is true. Or use values from isDuration or durationEvent + var instant = (bindings["isDuration"] === null && + bindings["durationEvent"] === null) || + bindings["isDuration"] == "false" || + bindings["durationEvent"] == "false"; + + var evt = new Timeline.DefaultEventSource.Event({ + id: bindings["id"], + start: parseDateTimeFunction(bindings["start"]), + end: parseDateTimeFunction(bindings["end"]), + latestStart: parseDateTimeFunction(bindings["latestStart"]), + earliestEnd: parseDateTimeFunction(bindings["earliestEnd"]), + instant: instant, // instant + text: bindings["title"], // text + description: bindings["description"], + image: this._resolveRelativeURL(bindings["image"], base), + link: this._resolveRelativeURL(bindings["link"] , base), + icon: this._resolveRelativeURL(bindings["icon"] , base), + color: bindings["color"], + textColor: bindings["textColor"], + hoverText: bindings["hoverText"], + caption: bindings["caption"], + classname: bindings["classname"], + tapeImage: bindings["tapeImage"], + tapeRepeat: bindings["tapeRepeat"], + eventID: bindings["eventID"], + trackNum: bindings["trackNum"] + }); + evt._bindings = bindings; + evt.getProperty = function(name) { + return this._bindings[name]; + }; + evt.setWikiInfo(wikiURL, wikiSection); + + this._events.add(evt); + added = true; + } + node = node.nextSibling; + } + + if (added) { + this._fire("onAddMany", []); + } +}; + +Timeline.DefaultEventSource.prototype.add = function(evt) { + this._events.add(evt); + this._fire("onAddOne", [evt]); +}; + +Timeline.DefaultEventSource.prototype.addMany = function(events) { + for (var i = 0; i < events.length; i++) { + this._events.add(events[i]); + } + this._fire("onAddMany", []); +}; + +Timeline.DefaultEventSource.prototype.clear = function() { + this._events.removeAll(); + this._fire("onClear", []); +}; + +Timeline.DefaultEventSource.prototype.getEvent = function(id) { + return this._events.getEvent(id); +}; + +Timeline.DefaultEventSource.prototype.getEventIterator = function(startDate, endDate) { + return this._events.getIterator(startDate, endDate); +}; + +Timeline.DefaultEventSource.prototype.getEventReverseIterator = function(startDate, endDate) { + return this._events.getReverseIterator(startDate, endDate); +}; + +Timeline.DefaultEventSource.prototype.getAllEventIterator = function() { + return this._events.getAllIterator(); +}; + +Timeline.DefaultEventSource.prototype.getCount = function() { + return this._events.getCount(); +}; + +Timeline.DefaultEventSource.prototype.getEarliestDate = function() { + return this._events.getEarliestDate(); +}; + +Timeline.DefaultEventSource.prototype.getLatestDate = function() { + return this._events.getLatestDate(); +}; + +Timeline.DefaultEventSource.prototype._fire = function(handlerName, args) { + for (var i = 0; i < this._listeners.length; i++) { + var listener = this._listeners[i]; + if (handlerName in listener) { + try { + listener[handlerName].apply(listener, args); + } catch (e) { + SimileAjax.Debug.exception(e); + } + } + } +}; + +Timeline.DefaultEventSource.prototype._getBaseURL = function(url) { + if (url.indexOf("://") < 0) { + var url2 = this._getBaseURL(document.location.href); + if (url.substr(0,1) == "/") { + url = url2.substr(0, url2.indexOf("/", url2.indexOf("://") + 3)) + url; + } else { + url = url2 + url; + } + } + + var i = url.lastIndexOf("/"); + if (i < 0) { + return ""; + } else { + return url.substr(0, i+1); + } +}; + +Timeline.DefaultEventSource.prototype._resolveRelativeURL = function(url, base) { + if (url == null || url == "") { + return url; + } else if (url.indexOf("://") > 0) { + return url; + } else if (url.substr(0,1) == "/") { + return base.substr(0, base.indexOf("/", base.indexOf("://") + 3)) + url; + } else { + return base + url; + } +}; + + +Timeline.DefaultEventSource.Event = function(args) { + // + // Attention developers! + // If you add a new event attribute, please be sure to add it to + // all three load functions: loadXML, loadSPARCL, loadJSON. + // Thanks! + // + // args is a hash/object. It supports the following keys. Most are optional + // id -- an internal id. Really shouldn't be used by events. + // Timeline library clients should use eventID + // eventID -- For use by library client when writing custom painters or + // custom fillInfoBubble + // start + // end + // latestStart + // earliestEnd + // instant -- boolean. Controls precise/non-precise logic & duration/instant issues + // text -- event source attribute 'title' -- used as the label on Timelines and in bubbles. + // description -- used in bubbles + // image -- used in bubbles + // link -- used in bubbles + // icon -- on the Timeline + // color -- Timeline label and tape color + // textColor -- Timeline label color, overrides color attribute + // hoverText -- deprecated, here for backwards compatibility. + // Superceeded by caption + // caption -- tooltip-like caption on the Timeline. Uses HTML title attribute + // classname -- used to set classname in Timeline. Enables better CSS selector rules + // tapeImage -- background image of the duration event's tape div on the Timeline + // tapeRepeat -- repeat attribute for tapeImage. {repeat | repeat-x | repeat-y } + + function cleanArg(arg) { + // clean up an arg + return (args[arg] != null && args[arg] != "") ? args[arg] : null; + } + + var id = args.id ? args.id.trim() : ""; + this._id = id.length > 0 ? id : Timeline.EventUtils.getNewEventID(); + + this._instant = args.instant || (args.end == null); + + this._start = args.start; + this._end = (args.end != null) ? args.end : args.start; + + this._latestStart = (args.latestStart != null) ? + args.latestStart : (args.instant ? this._end : this._start); + this._earliestEnd = (args.earliestEnd != null) ? args.earliestEnd : this._end; + + // check sanity of dates since incorrect dates will later cause calculation errors + // when painting + var err=[]; + if (this._start > this._latestStart) { + this._latestStart = this._start; + err.push("start is > latestStart");} + if (this._start > this._earliestEnd) { + this._earliestEnd = this._latestStart; + err.push("start is > earliestEnd");} + if (this._start > this._end) { + this._end = this._earliestEnd; + err.push("start is > end");} + if (this._latestStart > this._earliestEnd) { + this._earliestEnd = this._latestStart; + err.push("latestStart is > earliestEnd");} + if (this._latestStart > this._end) { + this._end = this._earliestEnd; + err.push("latestStart is > end");} + if (this._earliestEnd > this._end) { + this._end = this._earliestEnd; + err.push("earliestEnd is > end");} + + this._eventID = cleanArg('eventID'); + this._text = (args.text != null) ? SimileAjax.HTML.deEntify(args.text) : ""; // Change blank titles to "" + if (err.length > 0) { + this._text += " PROBLEM: " + err.join(", "); + } + + this._description = SimileAjax.HTML.deEntify(args.description); + this._image = cleanArg('image'); + this._link = cleanArg('link'); + this._title = cleanArg('hoverText'); + this._title = cleanArg('caption'); + + this._icon = cleanArg('icon'); + this._color = cleanArg('color'); + this._textColor = cleanArg('textColor'); + this._classname = cleanArg('classname'); + this._tapeImage = cleanArg('tapeImage'); + this._tapeRepeat = cleanArg('tapeRepeat'); + this._trackNum = cleanArg('trackNum'); + if (this._trackNum != null) { + this._trackNum = parseInt(this._trackNum); + } + + this._wikiURL = null; + this._wikiSection = null; +}; + +Timeline.DefaultEventSource.Event.prototype = { + getID: function() { return this._id; }, + + isInstant: function() { return this._instant; }, + isImprecise: function() { return this._start != this._latestStart || this._end != this._earliestEnd; }, + + getStart: function() { return this._start; }, + getEnd: function() { return this._end; }, + getLatestStart: function() { return this._latestStart; }, + getEarliestEnd: function() { return this._earliestEnd; }, + + getEventID: function() { return this._eventID; }, + getText: function() { return this._text; }, // title + getDescription: function() { return this._description; }, + getImage: function() { return this._image; }, + getLink: function() { return this._link; }, + + getIcon: function() { return this._icon; }, + getColor: function() { return this._color; }, + getTextColor: function() { return this._textColor; }, + getClassName: function() { return this._classname; }, + getTapeImage: function() { return this._tapeImage; }, + getTapeRepeat: function() { return this._tapeRepeat; }, + getTrackNum: function() { return this._trackNum; }, + + getProperty: function(name) { return null; }, + + getWikiURL: function() { return this._wikiURL; }, + getWikiSection: function() { return this._wikiSection; }, + setWikiInfo: function(wikiURL, wikiSection) { + this._wikiURL = wikiURL; + this._wikiSection = wikiSection; + }, + + fillDescription: function(elmt) { + elmt.innerHTML = this._description; + }, + fillWikiInfo: function(elmt) { + // Many bubbles will not support a wiki link. + // + // Strategy: assume no wiki link. If we do have + // enough parameters for one, then create it. + elmt.style.display = "none"; // default + + if (this._wikiURL == null || this._wikiSection == null) { + return; // EARLY RETURN + } + + // create the wikiID from the property or from the event text (the title) + var wikiID = this.getProperty("wikiID"); + if (wikiID == null || wikiID.length == 0) { + wikiID = this.getText(); // use the title as the backup wiki id + } + + if (wikiID == null || wikiID.length == 0) { + return; // No wikiID. Thus EARLY RETURN + } + + // ready to go... + elmt.style.display = "inline"; + wikiID = wikiID.replace(/\s/g, "_"); + var url = this._wikiURL + this._wikiSection.replace(/\s/g, "_") + "/" + wikiID; + var a = document.createElement("a"); + a.href = url; + a.target = "new"; + a.innerHTML = Timeline.strings[Timeline.clientLocale].wikiLinkLabel; + + elmt.appendChild(document.createTextNode("[")); + elmt.appendChild(a); + elmt.appendChild(document.createTextNode("]")); + }, + + fillTime: function(elmt, labeller) { + if (this._instant) { + if (this.isImprecise()) { + elmt.appendChild(elmt.ownerDocument.createTextNode(labeller.labelPrecise(this._start))); + elmt.appendChild(elmt.ownerDocument.createElement("br")); + elmt.appendChild(elmt.ownerDocument.createTextNode(labeller.labelPrecise(this._end))); + } else { + elmt.appendChild(elmt.ownerDocument.createTextNode(labeller.labelPrecise(this._start))); + } + } else { + if (this.isImprecise()) { + elmt.appendChild(elmt.ownerDocument.createTextNode( + labeller.labelPrecise(this._start) + " ~ " + labeller.labelPrecise(this._latestStart))); + elmt.appendChild(elmt.ownerDocument.createElement("br")); + elmt.appendChild(elmt.ownerDocument.createTextNode( + labeller.labelPrecise(this._earliestEnd) + " ~ " + labeller.labelPrecise(this._end))); + } else { + elmt.appendChild(elmt.ownerDocument.createTextNode(labeller.labelPrecise(this._start))); + elmt.appendChild(elmt.ownerDocument.createElement("br")); + elmt.appendChild(elmt.ownerDocument.createTextNode(labeller.labelPrecise(this._end))); + } + } + }, + + fillInfoBubble: function(elmt, theme, labeller) { + var doc = elmt.ownerDocument; + + var title = this.getText(); + var link = this.getLink(); + var image = this.getImage(); + + if (image != null) { + var img = doc.createElement("img"); + img.src = image; + + theme.event.bubble.imageStyler(img); + elmt.appendChild(img); + } + + var divTitle = doc.createElement("div"); + var textTitle = doc.createTextNode(title); + if (link != null) { + var a = doc.createElement("a"); + a.href = link; + a.appendChild(textTitle); + divTitle.appendChild(a); + } else { + divTitle.appendChild(textTitle); + } + theme.event.bubble.titleStyler(divTitle); + elmt.appendChild(divTitle); + + var divBody = doc.createElement("div"); + this.fillDescription(divBody); + theme.event.bubble.bodyStyler(divBody); + elmt.appendChild(divBody); + + var divTime = doc.createElement("div"); + this.fillTime(divTime, labeller); + theme.event.bubble.timeStyler(divTime); + elmt.appendChild(divTime); + + var divWiki = doc.createElement("div"); + this.fillWikiInfo(divWiki); + theme.event.bubble.wikiStyler(divWiki); + elmt.appendChild(divWiki); + } +}; + +