# HG changeset patch # User Julien Cristau # Date 1417431178 -3600 # Node ID cda1bdc3652e8ab3e6ab8f51308abfe3dbc3f901 # Parent fdcc500002ef13d2e3d0e44535ac2c1d6b8f81c8 [web] split timeline in an individual cube Closes #1279544 diff -r fdcc500002ef -r cda1bdc3652e __pkginfo__.py --- a/__pkginfo__.py Thu Feb 12 13:52:58 2015 +0100 +++ b/__pkginfo__.py Mon Dec 01 11:52:58 2014 +0100 @@ -115,8 +115,6 @@ [join('share', 'cubicweb', 'cubes', 'shared', 'data'), [join(_data_dir, fname) for fname in listdir(_data_dir) if not isdir(join(_data_dir, fname))]], - [join('share', 'cubicweb', 'cubes', 'shared', 'data', 'timeline'), - [join(_data_dir, 'timeline', fname) for fname in listdir(join(_data_dir, 'timeline'))]], [join('share', 'cubicweb', 'cubes', 'shared', 'data', 'images'), [join(_data_dir, 'images', fname) for fname in listdir(join(_data_dir, 'images'))]], [join('share', 'cubicweb', 'cubes', 'shared', 'data', 'jquery-treeview'), diff -r fdcc500002ef -r cda1bdc3652e doc/3.21.rst --- a/doc/3.21.rst Thu Feb 12 13:52:58 2015 +0100 +++ b/doc/3.21.rst Mon Dec 01 11:52:58 2014 +0100 @@ -1,6 +1,13 @@ What's new in CubicWeb 3.21? ============================ +Code movement +------------- + +The cubicweb.web.views.timeline module (providing the timeline-json, timeline +and static-timeline views) has moved to a standalone cube_ + +.. _cube: https://www.cubicweb.org/project/cubicweb-timeline Deprecated code drops --------------------- diff -r fdcc500002ef -r cda1bdc3652e doc/tools/pyjsrest.py --- a/doc/tools/pyjsrest.py Thu Feb 12 13:52:58 2015 +0100 +++ b/doc/tools/pyjsrest.py Mon Dec 01 11:52:58 2014 +0100 @@ -134,7 +134,6 @@ 'cubicweb.preferences', 'cubicweb.edition', 'cubicweb.reledit', - 'cubicweb.timeline-ext', ] FILES_TO_IGNORE = set([ @@ -152,7 +151,6 @@ 'cubicweb.fckcwconfig-full.js', 'cubicweb.goa.js', 'cubicweb.compat.js', - 'cubicweb.timeline-bundle.js', ]) if __name__ == '__main__': diff -r fdcc500002ef -r cda1bdc3652e web/data/cubicweb.timeline-bundle.js --- a/web/data/cubicweb.timeline-bundle.js Thu Feb 12 13:52:58 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10129 +0,0 @@ -/** - * This file contains timeline utilities - * :organization: Logilab - */ - -var SimileAjax_urlPrefix = BASE_URL + 'data/'; -var Timeline_urlPrefix = BASE_URL + 'data/'; - -/* - * Simile Ajax API - * - * Include this file in your HTML file as follows:: - * - * - * - * - */ - -if (typeof SimileAjax == "undefined") { - var SimileAjax = { - loaded: false, - loadingScriptsCount: 0, - error: null, - params: { bundle:"true" } - }; - - SimileAjax.Platform = new Object(); - /* - HACK: We need these 2 things here because we cannot simply append - a "); - return; - } catch (e) { - // fall through - } - } - - var script = doc.createElement("script"); - if (onerror) { - try { script.innerHTML = onerror; } catch(e) {} - script.setAttribute("onerror", onerror); - } - if (charset) { - script.setAttribute("charset", charset); - } - script.type = "text/javascript"; - script.language = "JavaScript"; - script.src = url; - return getHead(doc).appendChild(script); - }; - SimileAjax.includeJavascriptFiles = function(doc, urlPrefix, filenames) { - for (var i = 0; i < filenames.length; i++) { - SimileAjax.includeJavascriptFile(doc, urlPrefix + filenames[i]); - } - SimileAjax.loadingScriptsCount += filenames.length; - // XXX adim SimileAjax.includeJavascriptFile(doc, SimileAjax.urlPrefix + "scripts/signal.js?" + filenames.length); - }; - SimileAjax.includeCssFile = function(doc, url) { - if (doc.body == null) { - try { - doc.write(""); - return; - } catch (e) { - // fall through - } - } - - var link = doc.createElement("link"); - link.setAttribute("rel", "stylesheet"); - link.setAttribute("type", "text/css"); - link.setAttribute("href", url); - getHead(doc).appendChild(link); - }; - SimileAjax.includeCssFiles = function(doc, urlPrefix, filenames) { - for (var i = 0; i < filenames.length; i++) { - SimileAjax.includeCssFile(doc, urlPrefix + filenames[i]); - } - }; - - /** - * Append into urls each string in suffixes after prefixing it with urlPrefix. - * @param {Array} urls - * @param {String} urlPrefix - * @param {Array} suffixes - */ - SimileAjax.prefixURLs = function(urls, urlPrefix, suffixes) { - for (var i = 0; i < suffixes.length; i++) { - urls.push(urlPrefix + suffixes[i]); - } - }; - - /** - * Parse out the query parameters from a URL - * @param {String} url the url to parse, or location.href if undefined - * @param {Object} to optional object to extend with the parameters - * @param {Object} types optional object mapping keys to value types - * (String, Number, Boolean or Array, String by default) - * @return a key/value Object whose keys are the query parameter names - * @type Object - */ - SimileAjax.parseURLParameters = function(url, to, types) { - to = to || {}; - types = types || {}; - - if (typeof url == "undefined") { - url = location.href; - } - var q = url.indexOf("?"); - if (q < 0) { - return to; - } - url = (url+"#").slice(q+1, url.indexOf("#")); // toss the URL fragment - - var params = url.split("&"), param, parsed = {}; - var decode = window.decodeURIComponent || unescape; - for (var i = 0; param = params[i]; i++) { - var eq = param.indexOf("="); - var name = decode(param.slice(0,eq)); - var old = parsed[name]; - if (typeof old == "undefined") { - old = []; - } else if (!(old instanceof Array)) { - old = [old]; - } - parsed[name] = old.concat(decode(param.slice(eq+1))); - } - for (var i in parsed) { - if (!parsed.hasOwnProperty(i)) continue; - var type = types[i] || String; - var data = parsed[i]; - if (!(data instanceof Array)) { - data = [data]; - } - if (type === Boolean && data[0] == "false") { - to[i] = false; // because Boolean("false") === true - } else { - to[i] = type.apply(this, data); - } - } - return to; - }; - - (function() { - var javascriptFiles = [ - "jquery-1.2.6.js", - "platform.js", - "debug.js", - "xmlhttp.js", - "json.js", - "dom.js", - "graphics.js", - "date-time.js", - "string.js", - "html.js", - "data-structure.js", - "units.js", - - "ajax.js", - "history.js", - "window-manager.js" - ]; - var cssFiles = [ - "graphics.css" - ]; - - if (typeof SimileAjax_urlPrefix == "string") { - SimileAjax.urlPrefix = SimileAjax_urlPrefix; - } else { - var url = SimileAjax.findScript(document, "simile-ajax-api.js"); - if (url == null) { - SimileAjax.error = new Error("Failed to derive URL prefix for Simile Ajax API code files"); - return; - } - - SimileAjax.urlPrefix = url.substr(0, url.indexOf("simile-ajax-api.js")); - } - - SimileAjax.parseURLParameters(url, SimileAjax.params, {bundle:Boolean}); -// if (SimileAjax.params.bundle) { -// SimileAjax.includeJavascriptFiles(document, SimileAjax.urlPrefix, [ "simile-ajax-bundle.js" ]); -// } else { -// SimileAjax.includeJavascriptFiles(document, SimileAjax.urlPrefix + "scripts/", javascriptFiles); -// } -// SimileAjax.includeCssFiles(document, SimileAjax.urlPrefix + "styles/", cssFiles); - - SimileAjax.loaded = true; - })(); -} -/* - * Platform Utility Functions and Constants - * - */ - -/* This must be called after our jQuery has been loaded - but before control returns to user-code. -*/ -SimileAjax.jQuery = jQuery; -// SimileAjax.jQuery = jQuery.noConflict(true); -if (typeof window["$"] == "undefined") { - window.$ = SimileAjax.jQuery; -} - -SimileAjax.Platform.os = { - isMac: false, - isWin: false, - isWin32: false, - isUnix: false -}; -SimileAjax.Platform.browser = { - isIE: false, - isNetscape: false, - isMozilla: false, - isFirefox: false, - isOpera: false, - isSafari: false, - - majorVersion: 0, - minorVersion: 0 -}; - -(function() { - var an = navigator.appName.toLowerCase(); - var ua = navigator.userAgent.toLowerCase(); - - /* - * Operating system - */ - SimileAjax.Platform.os.isMac = (ua.indexOf('mac') != -1); - SimileAjax.Platform.os.isWin = (ua.indexOf('win') != -1); - SimileAjax.Platform.os.isWin32 = SimileAjax.Platform.isWin && ( - ua.indexOf('95') != -1 || - ua.indexOf('98') != -1 || - ua.indexOf('nt') != -1 || - ua.indexOf('win32') != -1 || - ua.indexOf('32bit') != -1 - ); - SimileAjax.Platform.os.isUnix = (ua.indexOf('x11') != -1); - - /* - * Browser - */ - SimileAjax.Platform.browser.isIE = (an.indexOf("microsoft") != -1); - SimileAjax.Platform.browser.isNetscape = (an.indexOf("netscape") != -1); - SimileAjax.Platform.browser.isMozilla = (ua.indexOf("mozilla") != -1); - SimileAjax.Platform.browser.isFirefox = (ua.indexOf("firefox") != -1); - SimileAjax.Platform.browser.isOpera = (an.indexOf("opera") != -1); - SimileAjax.Platform.browser.isSafari = (an.indexOf("safari") != -1); - - var parseVersionString = function(s) { - var a = s.split("."); - SimileAjax.Platform.browser.majorVersion = parseInt(a[0]); - SimileAjax.Platform.browser.minorVersion = parseInt(a[1]); - }; - var indexOf = function(s, sub, start) { - var i = s.indexOf(sub, start); - return i >= 0 ? i : s.length; - }; - - if (SimileAjax.Platform.browser.isMozilla) { - var offset = ua.indexOf("mozilla/"); - if (offset >= 0) { - parseVersionString(ua.substring(offset + 8, indexOf(ua, " ", offset))); - } - } - if (SimileAjax.Platform.browser.isIE) { - var offset = ua.indexOf("msie "); - if (offset >= 0) { - parseVersionString(ua.substring(offset + 5, indexOf(ua, ";", offset))); - } - } - if (SimileAjax.Platform.browser.isNetscape) { - var offset = ua.indexOf("rv:"); - if (offset >= 0) { - parseVersionString(ua.substring(offset + 3, indexOf(ua, ")", offset))); - } - } - if (SimileAjax.Platform.browser.isFirefox) { - var offset = ua.indexOf("firefox/"); - if (offset >= 0) { - parseVersionString(ua.substring(offset + 8, indexOf(ua, " ", offset))); - } - } - - if (!("localeCompare" in String.prototype)) { - String.prototype.localeCompare = function (s) { - if (this < s) return -1; - else if (this > s) return 1; - else return 0; - }; - } -})(); - -SimileAjax.Platform.getDefaultLocale = function() { - return SimileAjax.Platform.clientLocale; -}; -/* - * Debug Utility Functions - * - */ - -SimileAjax.Debug = { - silent: false -}; - -SimileAjax.Debug.log = function(msg) { - var f; - if ("console" in window && "log" in window.console) { // FireBug installed - f = function(msg2) { - console.log(msg2); - } - } else { - f = function(msg2) { - if (!SimileAjax.Debug.silent) { - alert(msg2); - } - } - } - SimileAjax.Debug.log = f; - f(msg); -}; - -SimileAjax.Debug.warn = function(msg) { - var f; - if ("console" in window && "warn" in window.console) { // FireBug installed - f = function(msg2) { - console.warn(msg2); - } - } else { - f = function(msg2) { - if (!SimileAjax.Debug.silent) { - alert(msg2); - } - } - } - SimileAjax.Debug.warn = f; - f(msg); -}; - -SimileAjax.Debug.exception = function(e, msg) { - var f, params = SimileAjax.parseURLParameters(); - if (params.errors == "throw" || SimileAjax.params.errors == "throw") { - f = function(e2, msg2) { - throw(e2); // do not hide from browser's native debugging features - }; - } else if ("console" in window && "error" in window.console) { // FireBug installed - f = function(e2, msg2) { - if (msg2 != null) { - console.error(msg2 + " %o", e2); - } else { - console.error(e2); - } - throw(e2); // do not hide from browser's native debugging features - }; - } else { - f = function(e2, msg2) { - if (!SimileAjax.Debug.silent) { - alert("Caught exception: " + msg2 + "\n\nDetails: " + ("description" in e2 ? e2.description : e2)); - } - throw(e2); // do not hide from browser's native debugging features - }; - } - SimileAjax.Debug.exception = f; - f(e, msg); -}; - -SimileAjax.Debug.objectToString = function(o) { - return SimileAjax.Debug._objectToString(o, ""); -}; - -SimileAjax.Debug._objectToString = function(o, indent) { - var indent2 = indent + " "; - if (typeof o == "object") { - var s = "{"; - for (n in o) { - s += indent2 + n + ": " + SimileAjax.Debug._objectToString(o[n], indent2) + "\n"; - } - s += indent + "}"; - return s; - } else if (typeof o == "array") { - var s = "["; - for (var n = 0; n < o.length; n++) { - s += SimileAjax.Debug._objectToString(o[n], indent2) + "\n"; - } - s += indent + "]"; - return s; - } else { - return o; - } -}; -/** - * @fileOverview XmlHttp utility functions - * @name SimileAjax.XmlHttp - */ - -SimileAjax.XmlHttp = new Object(); - -/** - * Callback for XMLHttp onRequestStateChange. - */ -SimileAjax.XmlHttp._onReadyStateChange = function(xmlhttp, fError, fDone) { - switch (xmlhttp.readyState) { - // 1: Request not yet made - // 2: Contact established with server but nothing downloaded yet - // 3: Called multiple while downloading in progress - - // Download complete - case 4: - try { - if (xmlhttp.status == 0 // file:// urls, works on Firefox - || xmlhttp.status == 200 // http:// urls - ) { - if (fDone) { - fDone(xmlhttp); - } - } else { - if (fError) { - fError( - xmlhttp.statusText, - xmlhttp.status, - xmlhttp - ); - } - } - } catch (e) { - SimileAjax.Debug.exception("XmlHttp: Error handling onReadyStateChange", e); - } - break; - } -}; - -/** - * Creates an XMLHttpRequest object. On the first run, this - * function creates a platform-specific function for - * instantiating an XMLHttpRequest object and then replaces - * itself with that function. - */ -SimileAjax.XmlHttp._createRequest = function() { - if (SimileAjax.Platform.browser.isIE) { - var programIDs = [ - "Msxml2.XMLHTTP", - "Microsoft.XMLHTTP", - "Msxml2.XMLHTTP.4.0" - ]; - for (var i = 0; i < programIDs.length; i++) { - try { - var programID = programIDs[i]; - var f = function() { - return new ActiveXObject(programID); - }; - var o = f(); - - // We are replacing the SimileAjax._createXmlHttpRequest - // function with this inner function as we've - // found out that it works. This is so that we - // don't have to do all the testing over again - // on subsequent calls. - SimileAjax.XmlHttp._createRequest = f; - - return o; - } catch (e) { - // silent - } - } - // fall through to try new XMLHttpRequest(); - } - - try { - var f = function() { - return new XMLHttpRequest(); - }; - var o = f(); - - // We are replacing the SimileAjax._createXmlHttpRequest - // function with this inner function as we've - // found out that it works. This is so that we - // don't have to do all the testing over again - // on subsequent calls. - SimileAjax.XmlHttp._createRequest = f; - - return o; - } catch (e) { - throw new Error("Failed to create an XMLHttpRequest object"); - } -}; - -/** - * Performs an asynchronous HTTP GET. - * - * @param {Function} fError a function of the form - function(statusText, statusCode, xmlhttp) - * @param {Function} fDone a function of the form function(xmlhttp) - */ -SimileAjax.XmlHttp.get = function(url, fError, fDone) { - var xmlhttp = SimileAjax.XmlHttp._createRequest(); - - xmlhttp.open("GET", url, true); - xmlhttp.onreadystatechange = function() { - SimileAjax.XmlHttp._onReadyStateChange(xmlhttp, fError, fDone); - }; - xmlhttp.send(null); -}; - -/** - * Performs an asynchronous HTTP POST. - * - * @param {Function} fError a function of the form - function(statusText, statusCode, xmlhttp) - * @param {Function} fDone a function of the form function(xmlhttp) - */ -SimileAjax.XmlHttp.post = function(url, body, fError, fDone) { - var xmlhttp = SimileAjax.XmlHttp._createRequest(); - - xmlhttp.open("POST", url, true); - xmlhttp.onreadystatechange = function() { - SimileAjax.XmlHttp._onReadyStateChange(xmlhttp, fError, fDone); - }; - xmlhttp.send(body); -}; - -SimileAjax.XmlHttp._forceXML = function(xmlhttp) { - try { - xmlhttp.overrideMimeType("text/xml"); - } catch (e) { - xmlhttp.setrequestheader("Content-Type", "text/xml"); - } -};/* - * Copied directly from http://www.json.org/json.js. - */ - -/* - json.js - 2006-04-28 - - This file adds these methods to JavaScript: - - object.toJSONString() - - This method produces a JSON text from an object. The - object must not contain any cyclical references. - - array.toJSONString() - - This method produces a JSON text from an array. The - array must not contain any cyclical references. - - string.parseJSON() - - This method parses a JSON text to produce an object or - array. It will return false if there is an error. -*/ - -SimileAjax.JSON = new Object(); - -(function () { - var m = { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '\\': '\\\\' - }; - var s = { - array: function (x) { - var a = ['['], b, f, i, l = x.length, v; - for (i = 0; i < l; i += 1) { - v = x[i]; - f = s[typeof v]; - if (f) { - v = f(v); - if (typeof v == 'string') { - if (b) { - a[a.length] = ','; - } - a[a.length] = v; - b = true; - } - } - } - a[a.length] = ']'; - return a.join(''); - }, - 'boolean': function (x) { - return String(x); - }, - 'null': function (x) { - return "null"; - }, - number: function (x) { - return isFinite(x) ? String(x) : 'null'; - }, - object: function (x) { - if (x) { - if (x instanceof Array) { - return s.array(x); - } - var a = ['{'], b, f, i, v; - for (i in x) { - v = x[i]; - f = s[typeof v]; - if (f) { - v = f(v); - if (typeof v == 'string') { - if (b) { - a[a.length] = ','; - } - a.push(s.string(i), ':', v); - b = true; - } - } - } - a[a.length] = '}'; - return a.join(''); - } - return 'null'; - }, - string: function (x) { - if (/["\\\x00-\x1f]/.test(x)) { - x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) { - var c = m[b]; - if (c) { - return c; - } - c = b.charCodeAt(); - return '\\u00' + - Math.floor(c / 16).toString(16) + - (c % 16).toString(16); - }); - } - return '"' + x + '"'; - } - }; - - SimileAjax.JSON.toJSONString = function(o) { - if (o instanceof Object) { - return s.object(o); - } else if (o instanceof Array) { - return s.array(o); - } else { - return o.toString(); - } - }; - - SimileAjax.JSON.parseJSON = function () { - try { - return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( - this.replace(/"(\\.|[^"\\])*"/g, ''))) && - eval('(' + this + ')'); - } catch (e) { - return false; - } - }; -})(); -/* - * DOM Utility Functions - * - */ - -SimileAjax.DOM = new Object(); - -SimileAjax.DOM.registerEventWithObject = function(elmt, eventName, obj, handlerName) { - SimileAjax.DOM.registerEvent(elmt, eventName, function(elmt2, evt, target) { - return obj[handlerName].call(obj, elmt2, evt, target); - }); -}; - -SimileAjax.DOM.registerEvent = function(elmt, eventName, handler) { - var handler2 = function(evt) { - evt = (evt) ? evt : ((event) ? event : null); - if (evt) { - var target = (evt.target) ? - evt.target : ((evt.srcElement) ? evt.srcElement : null); - if (target) { - target = (target.nodeType == 1 || target.nodeType == 9) ? - target : target.parentNode; - } - - return handler(elmt, evt, target); - } - return true; - } - - if (SimileAjax.Platform.browser.isIE) { - elmt.attachEvent("on" + eventName, handler2); - } else { - elmt.addEventListener(eventName, handler2, false); - } -}; - -SimileAjax.DOM.getPageCoordinates = function(elmt) { - var left = 0; - var top = 0; - - if (elmt.nodeType != 1) { - elmt = elmt.parentNode; - } - - var elmt2 = elmt; - while (elmt2 != null) { - left += elmt2.offsetLeft; - top += elmt2.offsetTop; - elmt2 = elmt2.offsetParent; - } - - var body = document.body; - while (elmt != null && elmt != body) { - if ("scrollLeft" in elmt) { - left -= elmt.scrollLeft; - top -= elmt.scrollTop; - } - elmt = elmt.parentNode; - } - - return { left: left, top: top }; -}; - -SimileAjax.DOM.getSize = function(elmt) { - var w = this.getStyle(elmt,"width"); - var h = this.getStyle(elmt,"height"); - if (w.indexOf("px") > -1) w = w.replace("px",""); - if (h.indexOf("px") > -1) h = h.replace("px",""); - return { - w: w, - h: h - } -} - -SimileAjax.DOM.getStyle = function(elmt, styleProp) { - if (elmt.currentStyle) { // IE - var style = elmt.currentStyle[styleProp]; - } else if (window.getComputedStyle) { // standard DOM - var style = document.defaultView.getComputedStyle(elmt, null).getPropertyValue(styleProp); - } else { - var style = ""; - } - return style; -} - -SimileAjax.DOM.getEventRelativeCoordinates = function(evt, elmt) { - if (SimileAjax.Platform.browser.isIE) { - if (evt.type == "mousewheel") { - var coords = SimileAjax.DOM.getPageCoordinates(elmt); - return { - x: evt.clientX - coords.left, - y: evt.clientY - coords.top - }; - } else { - return { - x: evt.offsetX, - y: evt.offsetY - }; - } - } else { - var coords = SimileAjax.DOM.getPageCoordinates(elmt); - - if ((evt.type == "DOMMouseScroll") && - SimileAjax.Platform.browser.isFirefox && - (SimileAjax.Platform.browser.majorVersion == 2)) { - // Due to: https://bugzilla.mozilla.org/show_bug.cgi?id=352179 - - return { - x: evt.screenX - coords.left, - y: evt.screenY - coords.top - }; - } else { - return { - x: evt.pageX - coords.left, - y: evt.pageY - coords.top - }; - } - } -}; - -SimileAjax.DOM.getEventPageCoordinates = function(evt) { - if (SimileAjax.Platform.browser.isIE) { - return { - x: evt.clientX + document.body.scrollLeft, - y: evt.clientY + document.body.scrollTop - }; - } else { - return { - x: evt.pageX, - y: evt.pageY - }; - } -}; - -SimileAjax.DOM.hittest = function(x, y, except) { - return SimileAjax.DOM._hittest(document.body, x, y, except); -}; - -SimileAjax.DOM._hittest = function(elmt, x, y, except) { - var childNodes = elmt.childNodes; - outer: for (var i = 0; i < childNodes.length; i++) { - var childNode = childNodes[i]; - for (var j = 0; j < except.length; j++) { - if (childNode == except[j]) { - continue outer; - } - } - - if (childNode.offsetWidth == 0 && childNode.offsetHeight == 0) { - /* - * Sometimes SPAN elements have zero width and height but - * they have children like DIVs that cover non-zero areas. - */ - var hitNode = SimileAjax.DOM._hittest(childNode, x, y, except); - if (hitNode != childNode) { - return hitNode; - } - } else { - var top = 0; - var left = 0; - - var node = childNode; - while (node) { - top += node.offsetTop; - left += node.offsetLeft; - node = node.offsetParent; - } - - if (left <= x && top <= y && (x - left) < childNode.offsetWidth && (y - top) < childNode.offsetHeight) { - return SimileAjax.DOM._hittest(childNode, x, y, except); - } else if (childNode.nodeType == 1 && childNode.tagName == "TR") { - /* - * Table row might have cells that span several rows. - */ - var childNode2 = SimileAjax.DOM._hittest(childNode, x, y, except); - if (childNode2 != childNode) { - return childNode2; - } - } - } - } - return elmt; -}; - -SimileAjax.DOM.cancelEvent = function(evt) { - evt.returnValue = false; - evt.cancelBubble = true; - if ("preventDefault" in evt) { - evt.preventDefault(); - } -}; - -SimileAjax.DOM.appendClassName = function(elmt, className) { - var classes = elmt.className.split(" "); - for (var i = 0; i < classes.length; i++) { - if (classes[i] == className) { - return; - } - } - classes.push(className); - elmt.className = classes.join(" "); -}; - -SimileAjax.DOM.createInputElement = function(type) { - var div = document.createElement("div"); - div.innerHTML = ""; - - return div.firstChild; -}; - -SimileAjax.DOM.createDOMFromTemplate = function(template) { - var result = {}; - result.elmt = SimileAjax.DOM._createDOMFromTemplate(template, result, null); - - return result; -}; - -SimileAjax.DOM._createDOMFromTemplate = function(templateNode, result, parentElmt) { - if (templateNode == null) { - /* - var node = doc.createTextNode("--null--"); - if (parentElmt != null) { - parentElmt.appendChild(node); - } - return node; - */ - return null; - } else if (typeof templateNode != "object") { - var node = document.createTextNode(templateNode); - if (parentElmt != null) { - parentElmt.appendChild(node); - } - return node; - } else { - var elmt = null; - if ("tag" in templateNode) { - var tag = templateNode.tag; - if (parentElmt != null) { - if (tag == "tr") { - elmt = parentElmt.insertRow(parentElmt.rows.length); - } else if (tag == "td") { - elmt = parentElmt.insertCell(parentElmt.cells.length); - } - } - if (elmt == null) { - elmt = tag == "input" ? - SimileAjax.DOM.createInputElement(templateNode.type) : - document.createElement(tag); - - if (parentElmt != null) { - parentElmt.appendChild(elmt); - } - } - } else { - elmt = templateNode.elmt; - if (parentElmt != null) { - parentElmt.appendChild(elmt); - } - } - - for (var attribute in templateNode) { - var value = templateNode[attribute]; - - if (attribute == "field") { - result[value] = elmt; - - } else if (attribute == "className") { - elmt.className = value; - } else if (attribute == "id") { - elmt.id = value; - } else if (attribute == "title") { - elmt.title = value; - } else if (attribute == "type" && elmt.tagName == "input") { - // do nothing - } else if (attribute == "style") { - for (n in value) { - var v = value[n]; - if (n == "float") { - n = SimileAjax.Platform.browser.isIE ? "styleFloat" : "cssFloat"; - } - elmt.style[n] = v; - } - } else if (attribute == "children") { - for (var i = 0; i < value.length; i++) { - SimileAjax.DOM._createDOMFromTemplate(value[i], result, elmt); - } - } else if (attribute != "tag" && attribute != "elmt") { - elmt.setAttribute(attribute, value); - } - } - return elmt; - } -} - -SimileAjax.DOM._cachedParent = null; -SimileAjax.DOM.createElementFromString = function(s) { - if (SimileAjax.DOM._cachedParent == null) { - SimileAjax.DOM._cachedParent = document.createElement("div"); - } - SimileAjax.DOM._cachedParent.innerHTML = s; - return SimileAjax.DOM._cachedParent.firstChild; -}; - -SimileAjax.DOM.createDOMFromString = function(root, s, fieldElmts) { - var elmt = typeof root == "string" ? document.createElement(root) : root; - elmt.innerHTML = s; - - var dom = { elmt: elmt }; - SimileAjax.DOM._processDOMChildrenConstructedFromString(dom, elmt, fieldElmts != null ? fieldElmts : {} ); - - return dom; -}; - -SimileAjax.DOM._processDOMConstructedFromString = function(dom, elmt, fieldElmts) { - var id = elmt.id; - if (id != null && id.length > 0) { - elmt.removeAttribute("id"); - if (id in fieldElmts) { - var parentElmt = elmt.parentNode; - parentElmt.insertBefore(fieldElmts[id], elmt); - parentElmt.removeChild(elmt); - - dom[id] = fieldElmts[id]; - return; - } else { - dom[id] = elmt; - } - } - - if (elmt.hasChildNodes()) { - SimileAjax.DOM._processDOMChildrenConstructedFromString(dom, elmt, fieldElmts); - } -}; - -SimileAjax.DOM._processDOMChildrenConstructedFromString = function(dom, elmt, fieldElmts) { - var node = elmt.firstChild; - while (node != null) { - var node2 = node.nextSibling; - if (node.nodeType == 1) { - SimileAjax.DOM._processDOMConstructedFromString(dom, node, fieldElmts); - } - node = node2; - } -}; -/** - * @fileOverview Graphics utility functions and constants - * @name SimileAjax.Graphics - */ - -SimileAjax.Graphics = new Object(); - -/** - * A boolean value indicating whether PNG translucency is supported on the - * user's browser or not. - * - * @type Boolean - */ -SimileAjax.Graphics.pngIsTranslucent = (!SimileAjax.Platform.browser.isIE) || (SimileAjax.Platform.browser.majorVersion > 6); -if (!SimileAjax.Graphics.pngIsTranslucent) { - SimileAjax.includeCssFile(document, SimileAjax.urlPrefix + "styles/graphics-ie6.css"); -} - -/* - * Opacity, translucency - * - */ -SimileAjax.Graphics._createTranslucentImage1 = function(url, verticalAlign) { - var elmt = document.createElement("img"); - elmt.setAttribute("src", url); - if (verticalAlign != null) { - elmt.style.verticalAlign = verticalAlign; - } - return elmt; -}; -SimileAjax.Graphics._createTranslucentImage2 = function(url, verticalAlign) { - var elmt = document.createElement("img"); - elmt.style.width = "1px"; // just so that IE will calculate the size property - elmt.style.height = "1px"; - elmt.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + url +"', sizingMethod='image')"; - elmt.style.verticalAlign = (verticalAlign != null) ? verticalAlign : "middle"; - return elmt; -}; - -/** - * Creates a DOM element for an img tag using the URL given. This - * is a convenience method that automatically includes the necessary CSS to - * allow for translucency, even on IE. - * - * @function - * @param {String} url the URL to the image - * @param {String} verticalAlign the CSS value for the image's vertical-align - * @return {Element} a DOM element containing the img tag - */ -SimileAjax.Graphics.createTranslucentImage = SimileAjax.Graphics.pngIsTranslucent ? - SimileAjax.Graphics._createTranslucentImage1 : - SimileAjax.Graphics._createTranslucentImage2; - -SimileAjax.Graphics._createTranslucentImageHTML1 = function(url, verticalAlign) { - return ""; -}; -SimileAjax.Graphics._createTranslucentImageHTML2 = function(url, verticalAlign) { - var style = - "width: 1px; height: 1px; " + - "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + url +"', sizingMethod='image');" + - (verticalAlign != null ? " vertical-align: " + verticalAlign + ";" : ""); - - return ""; -}; - -/** - * Creates an HTML string for an img tag using the URL given. - * This is a convenience method that automatically includes the necessary CSS - * to allow for translucency, even on IE. - * - * @function - * @param {String} url the URL to the image - * @param {String} verticalAlign the CSS value for the image's vertical-align - * @return {String} a string containing the img tag - */ -SimileAjax.Graphics.createTranslucentImageHTML = SimileAjax.Graphics.pngIsTranslucent ? - SimileAjax.Graphics._createTranslucentImageHTML1 : - SimileAjax.Graphics._createTranslucentImageHTML2; - -/** - * Sets the opacity on the given DOM element. - * - * @param {Element} elmt the DOM element to set the opacity on - * @param {Number} opacity an integer from 0 to 100 specifying the opacity - */ -SimileAjax.Graphics.setOpacity = function(elmt, opacity) { - if (SimileAjax.Platform.browser.isIE) { - elmt.style.filter = "progid:DXImageTransform.Microsoft.Alpha(Style=0,Opacity=" + opacity + ")"; - } else { - var o = (opacity / 100).toString(); - elmt.style.opacity = o; - elmt.style.MozOpacity = o; - } -}; - -/* - * Bubble - * - */ - -SimileAjax.Graphics.bubbleConfig = { - containerCSSClass: "simileAjax-bubble-container", - innerContainerCSSClass: "simileAjax-bubble-innerContainer", - contentContainerCSSClass: "simileAjax-bubble-contentContainer", - - borderGraphicSize: 50, - borderGraphicCSSClassPrefix: "simileAjax-bubble-border-", - - arrowGraphicTargetOffset: 33, // from tip of arrow to the side of the graphic that touches the content of the bubble - arrowGraphicLength: 100, // dimension of arrow graphic along the direction that the arrow points - arrowGraphicWidth: 49, // dimension of arrow graphic perpendicular to the direction that the arrow points - arrowGraphicCSSClassPrefix: "simileAjax-bubble-arrow-", - - closeGraphicCSSClass: "simileAjax-bubble-close", - - extraPadding: 20 -}; - -/** - * Creates a nice, rounded bubble popup with the given content in a div, - * page coordinates and a suggested width. The bubble will point to the - * location on the page as described by pageX and pageY. All measurements - * should be given in pixels. - * - * @param {Element} the content div - * @param {Number} pageX the x coordinate of the point to point to - * @param {Number} pageY the y coordinate of the point to point to - * @param {Number} contentWidth a suggested width of the content - * @param {String} orientation a string ("top", "bottom", "left", or "right") - * that describes the orientation of the arrow on the bubble - * @param {Number} maxHeight. Add a scrollbar div if bubble would be too tall. - * Default of 0 or null means no maximum - */ -SimileAjax.Graphics.createBubbleForContentAndPoint = function( - div, pageX, pageY, contentWidth, orientation, maxHeight) { - if (typeof contentWidth != "number") { - contentWidth = 300; - } - if (typeof maxHeight != "number") { - maxHeight = 0; - } - - div.style.position = "absolute"; - div.style.left = "-5000px"; - div.style.top = "0px"; - div.style.width = contentWidth + "px"; - document.body.appendChild(div); - - window.setTimeout(function() { - var width = div.scrollWidth + 10; - var height = div.scrollHeight + 10; - var scrollDivW = 0; // width of the possible inner container when we want vertical scrolling - if (maxHeight > 0 && height > maxHeight) { - height = maxHeight; - scrollDivW = width - 25; - } - - var bubble = SimileAjax.Graphics.createBubbleForPoint(pageX, pageY, width, height, orientation); - - document.body.removeChild(div); - div.style.position = "static"; - div.style.left = ""; - div.style.top = ""; - - // create a scroll div if needed - if (scrollDivW > 0) { - var scrollDiv = document.createElement("div"); - div.style.width = ""; - scrollDiv.style.width = scrollDivW + "px"; - scrollDiv.appendChild(div); - bubble.content.appendChild(scrollDiv); - } else { - div.style.width = width + "px"; - bubble.content.appendChild(div); - } - }, 200); -}; - -/** - * Creates a nice, rounded bubble popup with the given page coordinates and - * content dimensions. The bubble will point to the location on the page - * as described by pageX and pageY. All measurements should be given in - * pixels. - * - * @param {Number} pageX the x coordinate of the point to point to - * @param {Number} pageY the y coordinate of the point to point to - * @param {Number} contentWidth the width of the content box in the bubble - * @param {Number} contentHeight the height of the content box in the bubble - * @param {String} orientation a string ("top", "bottom", "left", or "right") - * that describes the orientation of the arrow on the bubble - * @return {Element} a DOM element for the newly created bubble - */ -SimileAjax.Graphics.createBubbleForPoint = function(pageX, pageY, contentWidth, contentHeight, orientation) { - contentWidth = parseInt(contentWidth, 10); // harden against bad input bugs - contentHeight = parseInt(contentHeight, 10); // getting numbers-as-strings - - var bubbleConfig = SimileAjax.Graphics.bubbleConfig; - var pngTransparencyClassSuffix = - SimileAjax.Graphics.pngIsTranslucent ? "pngTranslucent" : "pngNotTranslucent"; - - var bubbleWidth = contentWidth + 2 * bubbleConfig.borderGraphicSize; - var bubbleHeight = contentHeight + 2 * bubbleConfig.borderGraphicSize; - - var generatePngSensitiveClass = function(className) { - return className + " " + className + "-" + pngTransparencyClassSuffix; - }; - - /* - * Render container divs - */ - var div = document.createElement("div"); - div.className = generatePngSensitiveClass(bubbleConfig.containerCSSClass); - div.style.width = contentWidth + "px"; - div.style.height = contentHeight + "px"; - - var divInnerContainer = document.createElement("div"); - divInnerContainer.className = generatePngSensitiveClass(bubbleConfig.innerContainerCSSClass); - div.appendChild(divInnerContainer); - - /* - * Create layer for bubble - */ - var close = function() { - if (!bubble._closed) { - document.body.removeChild(bubble._div); - bubble._doc = null; - bubble._div = null; - bubble._content = null; - bubble._closed = true; - } - } - var bubble = { _closed: false }; - var layer = SimileAjax.WindowManager.pushLayer(close, true, div); - bubble._div = div; - bubble.close = function() { SimileAjax.WindowManager.popLayer(layer); } - - /* - * Render border graphics - */ - var createBorder = function(classNameSuffix) { - var divBorderGraphic = document.createElement("div"); - divBorderGraphic.className = generatePngSensitiveClass(bubbleConfig.borderGraphicCSSClassPrefix + classNameSuffix); - divInnerContainer.appendChild(divBorderGraphic); - }; - createBorder("top-left"); - createBorder("top-right"); - createBorder("bottom-left"); - createBorder("bottom-right"); - createBorder("left"); - createBorder("right"); - createBorder("top"); - createBorder("bottom"); - - /* - * Render content - */ - var divContentContainer = document.createElement("div"); - divContentContainer.className = generatePngSensitiveClass(bubbleConfig.contentContainerCSSClass); - divInnerContainer.appendChild(divContentContainer); - bubble.content = divContentContainer; - - /* - * Render close button - */ - var divClose = document.createElement("div"); - divClose.className = generatePngSensitiveClass(bubbleConfig.closeGraphicCSSClass); - divInnerContainer.appendChild(divClose); - SimileAjax.WindowManager.registerEventWithObject(divClose, "click", bubble, "close"); - - (function() { - var dims = SimileAjax.Graphics.getWindowDimensions(); - var docWidth = dims.w; - var docHeight = dims.h; - - var halfArrowGraphicWidth = Math.ceil(bubbleConfig.arrowGraphicWidth / 2); - - var createArrow = function(classNameSuffix) { - var divArrowGraphic = document.createElement("div"); - divArrowGraphic.className = generatePngSensitiveClass(bubbleConfig.arrowGraphicCSSClassPrefix + "point-" + classNameSuffix); - divInnerContainer.appendChild(divArrowGraphic); - return divArrowGraphic; - }; - - if (pageX - halfArrowGraphicWidth - bubbleConfig.borderGraphicSize - bubbleConfig.extraPadding > 0 && - pageX + halfArrowGraphicWidth + bubbleConfig.borderGraphicSize + bubbleConfig.extraPadding < docWidth) { - - /* - * Bubble can be positioned above or below the target point. - */ - - var left = pageX - Math.round(contentWidth / 2); - left = pageX < (docWidth / 2) ? - Math.max(left, bubbleConfig.extraPadding + bubbleConfig.borderGraphicSize) : - Math.min(left, docWidth - bubbleConfig.extraPadding - bubbleConfig.borderGraphicSize - contentWidth); - - if ((orientation && orientation == "top") || - (!orientation && - (pageY - - bubbleConfig.arrowGraphicTargetOffset - - contentHeight - - bubbleConfig.borderGraphicSize - - bubbleConfig.extraPadding > 0))) { - - /* - * Position bubble above the target point. - */ - - var divArrow = createArrow("down"); - divArrow.style.left = (pageX - halfArrowGraphicWidth - left) + "px"; - - div.style.left = left + "px"; - div.style.top = (pageY - bubbleConfig.arrowGraphicTargetOffset - contentHeight) + "px"; - - return; - } else if ((orientation && orientation == "bottom") || - (!orientation && - (pageY - + bubbleConfig.arrowGraphicTargetOffset - + contentHeight - + bubbleConfig.borderGraphicSize - + bubbleConfig.extraPadding < docHeight))) { - - /* - * Position bubble below the target point. - */ - - var divArrow = createArrow("up"); - divArrow.style.left = (pageX - halfArrowGraphicWidth - left) + "px"; - - div.style.left = left + "px"; - div.style.top = (pageY + bubbleConfig.arrowGraphicTargetOffset) + "px"; - - return; - } - } - - var top = pageY - Math.round(contentHeight / 2); - top = pageY < (docHeight / 2) ? - Math.max(top, bubbleConfig.extraPadding + bubbleConfig.borderGraphicSize) : - Math.min(top, docHeight - bubbleConfig.extraPadding - bubbleConfig.borderGraphicSize - contentHeight); - - if ((orientation && orientation == "left") || - (!orientation && - (pageX - - bubbleConfig.arrowGraphicTargetOffset - - contentWidth - - bubbleConfig.borderGraphicSize - - bubbleConfig.extraPadding > 0))) { - - /* - * Position bubble left of the target point. - */ - - var divArrow = createArrow("right"); - divArrow.style.top = (pageY - halfArrowGraphicWidth - top) + "px"; - - div.style.top = top + "px"; - div.style.left = (pageX - bubbleConfig.arrowGraphicTargetOffset - contentWidth) + "px"; - } else { - - /* - * Position bubble right of the target point, as the last resort. - */ - - var divArrow = createArrow("left"); - divArrow.style.top = (pageY - halfArrowGraphicWidth - top) + "px"; - - div.style.top = top + "px"; - div.style.left = (pageX + bubbleConfig.arrowGraphicTargetOffset) + "px"; - } - })(); - - document.body.appendChild(div); - - return bubble; -}; - -SimileAjax.Graphics.getWindowDimensions = function() { - if (typeof window.innerHeight == 'number') { - return { w:window.innerWidth, h:window.innerHeight }; // Non-IE - } else if (document.documentElement && document.documentElement.clientHeight) { - return { // IE6+, in "standards compliant mode" - w:document.documentElement.clientWidth, - h:document.documentElement.clientHeight - }; - } else if (document.body && document.body.clientHeight) { - return { // IE 4 compatible - w:document.body.clientWidth, - h:document.body.clientHeight - }; - } -}; - - -/** - * Creates a floating, rounded message bubble in the center of the window for - * displaying modal information, e.g. "Loading..." - * - * @param {Document} doc the root document for the page to render on - * @param {Object} an object with two properties, contentDiv and containerDiv, - * consisting of the newly created DOM elements - */ -SimileAjax.Graphics.createMessageBubble = function(doc) { - var containerDiv = doc.createElement("div"); - if (SimileAjax.Graphics.pngIsTranslucent) { - var topDiv = doc.createElement("div"); - topDiv.style.height = "33px"; - topDiv.style.background = "url(" + SimileAjax.urlPrefix + "images/message-top-left.png) top left no-repeat"; - topDiv.style.paddingLeft = "44px"; - containerDiv.appendChild(topDiv); - - var topRightDiv = doc.createElement("div"); - topRightDiv.style.height = "33px"; - topRightDiv.style.background = "url(" + SimileAjax.urlPrefix + "images/message-top-right.png) top right no-repeat"; - topDiv.appendChild(topRightDiv); - - var middleDiv = doc.createElement("div"); - middleDiv.style.background = "url(" + SimileAjax.urlPrefix + "images/message-left.png) top left repeat-y"; - middleDiv.style.paddingLeft = "44px"; - containerDiv.appendChild(middleDiv); - - var middleRightDiv = doc.createElement("div"); - middleRightDiv.style.background = "url(" + SimileAjax.urlPrefix + "images/message-right.png) top right repeat-y"; - middleRightDiv.style.paddingRight = "44px"; - middleDiv.appendChild(middleRightDiv); - - var contentDiv = doc.createElement("div"); - middleRightDiv.appendChild(contentDiv); - - var bottomDiv = doc.createElement("div"); - bottomDiv.style.height = "55px"; - bottomDiv.style.background = "url(" + SimileAjax.urlPrefix + "images/message-bottom-left.png) bottom left no-repeat"; - bottomDiv.style.paddingLeft = "44px"; - containerDiv.appendChild(bottomDiv); - - var bottomRightDiv = doc.createElement("div"); - bottomRightDiv.style.height = "55px"; - bottomRightDiv.style.background = "url(" + SimileAjax.urlPrefix + "images/message-bottom-right.png) bottom right no-repeat"; - bottomDiv.appendChild(bottomRightDiv); - } else { - containerDiv.style.border = "2px solid #7777AA"; - containerDiv.style.padding = "20px"; - containerDiv.style.background = "white"; - SimileAjax.Graphics.setOpacity(containerDiv, 90); - - var contentDiv = doc.createElement("div"); - containerDiv.appendChild(contentDiv); - } - - return { - containerDiv: containerDiv, - contentDiv: contentDiv - }; -}; - -/* - * Animation - * - */ - -/** - * Creates an animation for a function, and an interval of values. The word - * "animation" here is used in the sense of repeatedly calling a function with - * a current value from within an interval, and a delta value. - * - * @param {Function} f a function to be called every 50 milliseconds throughout - * the animation duration, of the form f(current, delta), where current is - * the current value within the range and delta is the current change. - * @param {Number} from a starting value - * @param {Number} to an ending value - * @param {Number} duration the duration of the animation in milliseconds - * @param {Function} [cont] an optional function that is called at the end of - * the animation, i.e. a continuation. - * @return {SimileAjax.Graphics._Animation} a new animation object - */ -SimileAjax.Graphics.createAnimation = function(f, from, to, duration, cont) { - return new SimileAjax.Graphics._Animation(f, from, to, duration, cont); -}; - -SimileAjax.Graphics._Animation = function(f, from, to, duration, cont) { - this.f = f; - this.cont = (typeof cont == "function") ? cont : function() {}; - - this.from = from; - this.to = to; - this.current = from; - - this.duration = duration; - this.start = new Date().getTime(); - this.timePassed = 0; -}; - -/** - * Runs this animation. - */ -SimileAjax.Graphics._Animation.prototype.run = function() { - var a = this; - window.setTimeout(function() { a.step(); }, 50); -}; - -/** - * Increments this animation by one step, and then continues the animation with - * run(). - */ -SimileAjax.Graphics._Animation.prototype.step = function() { - this.timePassed += 50; - - var timePassedFraction = this.timePassed / this.duration; - var parameterFraction = -Math.cos(timePassedFraction * Math.PI) / 2 + 0.5; - var current = parameterFraction * (this.to - this.from) + this.from; - - try { - this.f(current, current - this.current); - } catch (e) { - } - this.current = current; - - if (this.timePassed < this.duration) { - this.run(); - } else { - this.f(this.to, 0); - this["cont"](); - } -}; - -/* - * CopyPasteButton - * - * Adapted from http://spaces.live.com/editorial/rayozzie/demo/liveclip/liveclipsample/techPreview.html. - * - */ - -/** - * Creates a button and textarea for displaying structured data and copying it - * to the clipboard. The data is dynamically generated by the given - * createDataFunction parameter. - * - * @param {String} image an image URL to use as the background for the - * generated box - * @param {Number} width the width in pixels of the generated box - * @param {Number} height the height in pixels of the generated box - * @param {Function} createDataFunction a function that is called with no - * arguments to generate the structured data - * @return a new DOM element - */ -SimileAjax.Graphics.createStructuredDataCopyButton = function(image, width, height, createDataFunction) { - var div = document.createElement("div"); - div.style.position = "relative"; - div.style.display = "inline"; - div.style.width = width + "px"; - div.style.height = height + "px"; - div.style.overflow = "hidden"; - div.style.margin = "2px"; - - if (SimileAjax.Graphics.pngIsTranslucent) { - div.style.background = "url(" + image + ") no-repeat"; - } else { - div.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + image +"', sizingMethod='image')"; - } - - var style; - if (SimileAjax.Platform.browser.isIE) { - style = "filter:alpha(opacity=0)"; - } else { - style = "opacity: 0"; - } - div.innerHTML = "