diff --git a/frontend-js/src/main/css/global.css b/frontend-js/src/main/css/global.css index df34f9477d50c1ee7c93ff5880d19685cbd0681d..c72de9f83c7cbc4dc258674be5bef70f29f49d7c 100644 --- a/frontend-js/src/main/css/global.css +++ b/frontend-js/src/main/css/global.css @@ -42,25 +42,25 @@ clear: both; } -.mapChartNameDiv { +.minerva-chart-name { width: 150px; float: left; display: inline-block; } -.mapChartRowEvenDiv { +.minerva-chart-row-even, .minerva-chart-row-odd { + position: relative; white-space: nowrap; overflow: hidden; margin: 1px; width: 360px; +} + +.minerva-chart-row-even { background-color: #D3D3D3; } -.mapChartRowOddDiv { - white-space: nowrap; - overflow: hidden; - margin: 1px; - width: 360px; +.minerva-chart-row-odd { background-color: #C0C0C0; } diff --git a/frontend-js/src/main/js/Functions.js b/frontend-js/src/main/js/Functions.js index b04ce60a4f83bda5b68af027d2add63f15c1dffb..b233ee58d6325cbc9a2ed659ee42cc9409f0a316 100644 --- a/frontend-js/src/main/js/Functions.js +++ b/frontend-js/src/main/js/Functions.js @@ -1,636 +1,675 @@ -"use strict"; - -var Promise = require("bluebird"); -var Point = require('./map/canvas/Point'); - -/* exported logger */ - -var logger = require('./logger'); - -var xss = require('xss'); - -var Functions = {}; - -/** - * Bounds value between opt_min and opt_max (result will be not smaller than - * opt_min and not bigger than opt_max). - */ -Functions.bound = function (value, minVal, maxVal) { - if (minVal !== null && minVal !== undefined) { - value = Math.max(value, minVal); - } - if (maxVal !== null && maxVal !== undefined) { - value = Math.min(value, maxVal); - } - return value; -}; - -Functions.degreesToRadians = function (deg) { - return deg * (Math.PI / 180); -}; - -Functions.radiansToDegrees = function (rad) { - return rad / (Math.PI / 180); -}; - -Functions.intToColorString = function (value) { - /* jslint bitwise: true */ - var trimmedValue = (value & 0xFFFFFF); - var colorStr = trimmedValue.toString(16); - while (colorStr.length < 6) { - colorStr = "0" + colorStr; - } - return '#' + colorStr; -}; - -/** - * - * @param value - * @returns {number|undefined} - */ -Functions.getIntOrUndefined = function (value) { - if (Functions.isInt(value)) { - return value; - } else if (value === undefined || value === null) { - return undefined; - } else { - logger.warn("Invalid argument type: " + value); - return undefined; - } -}; - - -/** - * - * @param {string} color - * @param {number} opacity - * @returns {string} - */ -Functions.colorToRgbaString = function (color, opacity) { - if (color[0] !== '#' || color.length !== 7) { - throw new Error("Expected color in #RRGGBB format"); - } - var red = parseInt(color.substr(1, 2), 16); - var green = parseInt(color.substr(3, 2), 16); - var blue = parseInt(color.substr(5, 2), 16); - var alpha = opacity !== undefined ? opacity : 1.0; - return "rgba(" + red + "," + green + "," + blue + "," + alpha + ")"; -}; - -/** - * Returns stack trace. - * - * @returns {string} stack trace - */ -Functions.stackTrace = function () { - var err = new Error(); - return err.stack; -}; - -/** - * Returns the position of the element on html page. - * - * @param element - * element for which we want to get the position (top left corner) - * - * @return {Point} coordinates of the element - * - */ -Functions.getPosition = function (element) { - var xPosition = 0; - var yPosition = 0; - - while (element) { - xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft); - yPosition += (element.offsetTop - element.scrollTop + element.clientTop); - element = element.offsetParent; - } - return new Point(xPosition, yPosition); -}; - -/** - * Checks if the point given as a first argument belongs to a polygon defined as - * a second parameter. Both: point and polygon should use google.map.point - * class. - * - * @param {Point} point - * point which we want to check - * - * @param {Point[]} polygon - * polygon where we check the point - */ - -Functions.pointInsidePolygon = function (point, polygon) { - var x = point.x; - var y = point.y; - - var inside = false; - for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { - var xi = polygon[i].x, yi = polygon[i].y; - var xj = polygon[j].x, yj = polygon[j].y; - var intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - if (intersect) { - inside = !inside; - } - } - return inside; -}; - -/** - * In a browser variable we store information about browser user is currently - * using. Right now only IE is supported. - */ -Functions.browser = { - init: function () { - - this.name = "Unknown"; - this.version = "Unknown"; - - if (typeof navigator !== 'undefined') { - // Get the user agent string - var ua = navigator.userAgent; - this.compatibilityMode = false; - var re; - if (navigator.appName === 'Microsoft Internet Explorer') { - this.name = "IE"; - re = new RegExp("MSIE ([0-9]+[\.0-9]*)"); - if (re.exec(ua) !== undefined && re.exec(ua) !== null) { - this.version = parseFloat(RegExp.$1); - } - if (ua.indexOf("MSIE 7.0") > -1) { - this.compatibilityMode = true; - } - } else if (navigator.appName === 'Netscape') { - this.name = "Other"; - ua = navigator.userAgent; - re = new RegExp("Trident/.*rv[ :]*([0-9]{1,}[\.0-9]{0,})"); - if (re.exec(ua) !== undefined && re.exec(ua) !== null) { - this.version = parseFloat(RegExp.$1); - } - } - } - } -}; - -Functions.browser.init(); - -/** - * Returns true if parameter is integer, false otherwise. - * - * @param n - * object to check - */ -Functions.isInt = function (n) { - return Number(n) === n && n % 1 === 0; -}; - -/** - * Returns true if parameter is a DOM element, false otherwise. - * - * @param o - * object to check - */ -Functions.isDomElement = function (o) { - if (!o) { - return false; - } - return (typeof HTMLElement === "object" ? o instanceof HTMLElement : // DOM2 - o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string"); -}; - -/** - * - * @returns {Promise<string>} - */ -Functions.overlayToColor = function (elementOverlay) { - var self = this; - /* jslint bitwise: true */ - if (elementOverlay === null || elementOverlay === undefined) { - return Promise.reject("elementOverlay cannot be null!"); - } else if (elementOverlay.color !== undefined && elementOverlay.color !== null) { - return Promise.resolve(self.intToColorString(elementOverlay.color.rgb)); - } else { - var ratio = 0; - var promiseColors; - if (elementOverlay.value !== undefined && elementOverlay.value !== null) { - if (elementOverlay.value < 0) { - ratio = -elementOverlay.value; - promiseColors = [ServerConnector.getMinOverlayColorInt(), ServerConnector.getNeutralOverlayColorInt()]; - } else { - ratio = elementOverlay.value; - promiseColors = [ServerConnector.getMaxOverlayColorInt(), ServerConnector.getNeutralOverlayColorInt()]; - } - } else { - ratio = 1; - promiseColors = [ServerConnector.getSimpleOverlayColorInt(), ServerConnector.getNeutralOverlayColorInt()]; - } - - return Promise.all(promiseColors).then(function (colors) { - var maxColor = colors[0]; - var neutralColor = colors[1]; - - ratio = 1 - ratio; - var MAX_RED = 0xFF0000; - var MAX_GREEN = 0x00FF00; - var MAX_BLUE = 0x0000FF; - - var red = maxColor & MAX_RED; - var neutralRed = neutralColor & MAX_RED; - - red = red + (neutralRed - red) * ratio; - red = parseInt(red); - red = red & MAX_RED; - - var green = maxColor & MAX_GREEN; - var neutralGreen = neutralColor & MAX_GREEN; - green = green + (neutralGreen - green) * ratio; - green = parseInt(green); - green = green & MAX_GREEN; - - var blue = maxColor & MAX_BLUE; - var neutralBlue = neutralColor & MAX_BLUE; - blue = blue + (neutralBlue - blue) * ratio; - blue = parseInt(blue); - blue = blue & MAX_BLUE; - - var color = red | green | blue; - return self.intToColorString(color); - }); - } -}; - -Functions.getElementByName = function (element, name) { - if (element !== undefined) { - if (element.getAttribute("name") === name) { - return element; - } - var children = element.children; - for (var i = 0; i < children.length; i++) { - var child = children[i]; - var res = this.getElementByName(child, name); - if (res !== undefined) { - return res; - } - } - } - return undefined; -}; - - -/** - * - * @param {HTMLElement}element - * @param {string} name class name - * @returns {HTMLElement|undefined} - */ -Functions.getElementByClassName = function (element, name) { - if (name.indexOf(".") !== 0) { - name = "." + name; - } - return $(name, element)[0]; -}; - -/** - * - * @param {Object} params - * @param {string} params.type type of the {HTMLElement} to be created - * @param {string} [params.inputType] type of the input to be created - * @param {string} [params.className] css class of the element - * @param {string} [params.style] css styling - * @param {string} [params.value] - * @param {string|HTMLElement} [params.content] - * - * @returns {HTMLElement} - */ -Functions.createElement = function (params) { - var result = document.createElement(params.type); - if (params.id !== null && params.id !== undefined) { - result.id = params.id; - } - if (params.name !== null && params.name !== undefined) { - result.setAttribute("name", params.name); - } - if (params.className !== null && params.className !== undefined) { - result.className = params.className; - } - if (params.inputType !== null && params.inputType !== undefined) { - result.type = params.inputType; - } - if (params.content !== null && params.content !== undefined) { - if (Functions.isDomElement(params.content)) { - result.appendChild(params.content); - } else if (params.xss !== false) { - var content = xss(params.content); - if (content !== params.content) { - logger.warn("XSS changed content: " + params.content); - } - result.innerHTML = content; - } else { - result.innerHTML = params.content; - } - } - if (params.style !== null && params.style !== undefined) { - result.style.cssText = params.style; - } - if (params.onclick !== null && params.onclick !== undefined) { - result.onclick = params.onclick; - } - if (params.onchange !== null && params.onchange !== undefined) { - result.onchange = params.onchange; - } - if (params.href !== null && params.href !== undefined) { - result.href = params.href; - } - if (params.src !== null && params.src !== undefined) { - result.src = params.src; - } - if (params.value !== null && params.value !== undefined) { - result.value = params.value; - } - if (params.title !== null && params.title !== undefined) { - result.title = params.title; - } - if (params.index !== null && params.index !== undefined) { - result.index = params.index; - } - if (params.data !== null && params.data !== undefined) { - $(result).attr("data", params.data); - } - return result; -}; - -function sqr(x) { - return x * x; -} - -function dist2(v, w) { - return sqr(v.x - w.x) + sqr(v.y - w.y); -} - -function distToSegmentSquared(p, v, w) { - var l2 = dist2(v, w); - - if (l2 === 0) { - return dist2(p, v); - } - - var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2; - - if (t < 0) { - return dist2(p, v); - } - if (t > 1) { - return dist2(p, w); - } - - return dist2(p, new Point(v.x + t * (w.x - v.x), v.y + t * (w.y - v.y))); -} - -Functions.distance = function (p1, el2) { - if (el2 instanceof Point) { - var p2 = el2; - return Math.sqrt((Math.pow(p1.x - p2.x, 2)) + (Math.pow(p1.y - p2.y, 2))); - } else { - return Math.sqrt(distToSegmentSquared(p1, el2.start, el2.end)); - } -}; - -Functions.removeChildren = function (element) { - while (element.firstChild) { - element.removeChild(element.firstChild); - } -}; - -/** - * - * @returns {Promise} resolved after javascript is loaded - */ -Functions.loadScript = function (url) { - return new Promise(function (resolve) { - var scriptExists = false; - var scripts = document.getElementsByTagName('script'); - for (var i = scripts.length; i--;) { - if (scripts[i].src === url) - scriptExists = true; - } - if (!scriptExists) { - var head = document.getElementsByTagName('head')[0]; - var script = document.createElement('script'); - script.type = 'text/javascript'; - script.src = url; - script.onload = function () { - resolve(); - }; - head.appendChild(script); - } else { - resolve(); - } - }); -}; - -Functions.computeMD5 = function (s) { - function L(k, d) { - return (k << d) | (k >>> (32 - d)) - } - - function K(G, k) { - var I, d, F, H, x; - F = (G & 2147483648); - H = (k & 2147483648); - I = (G & 1073741824); - d = (k & 1073741824); - x = (G & 1073741823) + (k & 1073741823); - if (I & d) { - return (x ^ 2147483648 ^ F ^ H) - } - if (I | d) { - if (x & 1073741824) { - return (x ^ 3221225472 ^ F ^ H) - } else { - return (x ^ 1073741824 ^ F ^ H) - } - } else { - return (x ^ F ^ H) - } - } - - function r(d, F, k) { - return (d & F) | ((~d) & k) - } - - function q(d, F, k) { - return (d & k) | (F & (~k)) - } - - function p(d, F, k) { - return (d ^ F ^ k) - } - - function n(d, F, k) { - return (F ^ (d | (~k))) - } - - function u(G, F, aa, Z, k, H, I) { - G = K(G, K(K(r(F, aa, Z), k), I)); - return K(L(G, H), F) - } - - function f(G, F, aa, Z, k, H, I) { - G = K(G, K(K(q(F, aa, Z), k), I)); - return K(L(G, H), F) - } - - function D(G, F, aa, Z, k, H, I) { - G = K(G, K(K(p(F, aa, Z), k), I)); - return K(L(G, H), F) - } - - function t(G, F, aa, Z, k, H, I) { - G = K(G, K(K(n(F, aa, Z), k), I)); - return K(L(G, H), F) - } - - function e(G) { - var Z; - var F = G.length; - var x = F + 8; - var k = (x - (x % 64)) / 64; - var I = (k + 1) * 16; - var aa = Array(I - 1); - var d = 0; - var H = 0; - while (H < F) { - Z = (H - (H % 4)) / 4; - d = (H % 4) * 8; - aa[Z] = (aa[Z] | (G.charCodeAt(H) << d)); - H++ - } - Z = (H - (H % 4)) / 4; - d = (H % 4) * 8; - aa[Z] = aa[Z] | (128 << d); - aa[I - 2] = F << 3; - aa[I - 1] = F >>> 29; - return aa - } - - function B(x) { - var k = "", F = "", G, d; - for (d = 0; d <= 3; d++) { - G = (x >>> (d * 8)) & 255; - F = "0" + G.toString(16); - k = k + F.substr(F.length - 2, 2) - } - return k - } - - function J(k) { - k = k.replace(/rn/g, "n"); - var d = ""; - for (var F = 0; F < k.length; F++) { - var x = k.charCodeAt(F); - if (x < 128) { - d += String.fromCharCode(x) - } else { - if ((x > 127) && (x < 2048)) { - d += String.fromCharCode((x >> 6) | 192); - d += String.fromCharCode((x & 63) | 128) - } else { - d += String.fromCharCode((x >> 12) | 224); - d += String.fromCharCode(((x >> 6) & 63) | 128); - d += String.fromCharCode((x & 63) | 128) - } - } - } - return d - } - - var C = Array(); - var P, h, E, v, g, Y, X, W, V; - var S = 7, Q = 12, N = 17, M = 22; - var A = 5, z = 9, y = 14, w = 20; - var o = 4, m = 11, l = 16, j = 23; - var U = 6, T = 10, R = 15, O = 21; - s = J(s); - C = e(s); - Y = 1732584193; - X = 4023233417; - W = 2562383102; - V = 271733878; - for (P = 0; P < C.length; P += 16) { - h = Y; - E = X; - v = W; - g = V; - Y = u(Y, X, W, V, C[P + 0], S, 3614090360); - V = u(V, Y, X, W, C[P + 1], Q, 3905402710); - W = u(W, V, Y, X, C[P + 2], N, 606105819); - X = u(X, W, V, Y, C[P + 3], M, 3250441966); - Y = u(Y, X, W, V, C[P + 4], S, 4118548399); - V = u(V, Y, X, W, C[P + 5], Q, 1200080426); - W = u(W, V, Y, X, C[P + 6], N, 2821735955); - X = u(X, W, V, Y, C[P + 7], M, 4249261313); - Y = u(Y, X, W, V, C[P + 8], S, 1770035416); - V = u(V, Y, X, W, C[P + 9], Q, 2336552879); - W = u(W, V, Y, X, C[P + 10], N, 4294925233); - X = u(X, W, V, Y, C[P + 11], M, 2304563134); - Y = u(Y, X, W, V, C[P + 12], S, 1804603682); - V = u(V, Y, X, W, C[P + 13], Q, 4254626195); - W = u(W, V, Y, X, C[P + 14], N, 2792965006); - X = u(X, W, V, Y, C[P + 15], M, 1236535329); - Y = f(Y, X, W, V, C[P + 1], A, 4129170786); - V = f(V, Y, X, W, C[P + 6], z, 3225465664); - W = f(W, V, Y, X, C[P + 11], y, 643717713); - X = f(X, W, V, Y, C[P + 0], w, 3921069994); - Y = f(Y, X, W, V, C[P + 5], A, 3593408605); - V = f(V, Y, X, W, C[P + 10], z, 38016083); - W = f(W, V, Y, X, C[P + 15], y, 3634488961); - X = f(X, W, V, Y, C[P + 4], w, 3889429448); - Y = f(Y, X, W, V, C[P + 9], A, 568446438); - V = f(V, Y, X, W, C[P + 14], z, 3275163606); - W = f(W, V, Y, X, C[P + 3], y, 4107603335); - X = f(X, W, V, Y, C[P + 8], w, 1163531501); - Y = f(Y, X, W, V, C[P + 13], A, 2850285829); - V = f(V, Y, X, W, C[P + 2], z, 4243563512); - W = f(W, V, Y, X, C[P + 7], y, 1735328473); - X = f(X, W, V, Y, C[P + 12], w, 2368359562); - Y = D(Y, X, W, V, C[P + 5], o, 4294588738); - V = D(V, Y, X, W, C[P + 8], m, 2272392833); - W = D(W, V, Y, X, C[P + 11], l, 1839030562); - X = D(X, W, V, Y, C[P + 14], j, 4259657740); - Y = D(Y, X, W, V, C[P + 1], o, 2763975236); - V = D(V, Y, X, W, C[P + 4], m, 1272893353); - W = D(W, V, Y, X, C[P + 7], l, 4139469664); - X = D(X, W, V, Y, C[P + 10], j, 3200236656); - Y = D(Y, X, W, V, C[P + 13], o, 681279174); - V = D(V, Y, X, W, C[P + 0], m, 3936430074); - W = D(W, V, Y, X, C[P + 3], l, 3572445317); - X = D(X, W, V, Y, C[P + 6], j, 76029189); - Y = D(Y, X, W, V, C[P + 9], o, 3654602809); - V = D(V, Y, X, W, C[P + 12], m, 3873151461); - W = D(W, V, Y, X, C[P + 15], l, 530742520); - X = D(X, W, V, Y, C[P + 2], j, 3299628645); - Y = t(Y, X, W, V, C[P + 0], U, 4096336452); - V = t(V, Y, X, W, C[P + 7], T, 1126891415); - W = t(W, V, Y, X, C[P + 14], R, 2878612391); - X = t(X, W, V, Y, C[P + 5], O, 4237533241); - Y = t(Y, X, W, V, C[P + 12], U, 1700485571); - V = t(V, Y, X, W, C[P + 3], T, 2399980690); - W = t(W, V, Y, X, C[P + 10], R, 4293915773); - X = t(X, W, V, Y, C[P + 1], O, 2240044497); - Y = t(Y, X, W, V, C[P + 8], U, 1873313359); - V = t(V, Y, X, W, C[P + 15], T, 4264355552); - W = t(W, V, Y, X, C[P + 6], R, 2734768916); - X = t(X, W, V, Y, C[P + 13], O, 1309151649); - Y = t(Y, X, W, V, C[P + 4], U, 4149444226); - V = t(V, Y, X, W, C[P + 11], T, 3174756917); - W = t(W, V, Y, X, C[P + 2], R, 718787259); - X = t(X, W, V, Y, C[P + 9], O, 3951481745); - Y = K(Y, h); - X = K(X, E); - W = K(W, v); - V = K(V, g) - } - var i = B(Y) + B(X) + B(W) + B(V); - return i.toLowerCase() -}; -module.exports = Functions; +"use strict"; + +var Promise = require("bluebird"); +var Point = require('./map/canvas/Point'); + +var logger = require('./logger'); + +var xss = require('xss'); + +function Functions() { + /** + * In a browser variable we store information about browser user is currently + * using. Right now only IE is supported. + */ + this.browser = { + init: function () { + + this.name = "Unknown"; + this.version = "Unknown"; + + if (typeof navigator !== 'undefined') { + // Get the user agent string + var ua = navigator.userAgent; + this.compatibilityMode = false; + var re; + if (navigator.appName === 'Microsoft Internet Explorer') { + this.name = "IE"; + re = new RegExp("MSIE ([0-9]+[\.0-9]*)"); + if (re.exec(ua) !== undefined && re.exec(ua) !== null) { + this.version = parseFloat(RegExp.$1); + } + if (ua.indexOf("MSIE 7.0") > -1) { + this.compatibilityMode = true; + } + } else if (navigator.appName === 'Netscape') { + this.name = "Other"; + ua = navigator.userAgent; + re = new RegExp("Trident/.*rv[ :]*([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) !== undefined && re.exec(ua) !== null) { + this.version = parseFloat(RegExp.$1); + } + } + } + } + }; + + this.browser.init(); +} + +/** + * Bounds value between opt_min and opt_max (result will be not smaller than + * opt_min and not bigger than opt_max). + */ +Functions.prototype.bound = function (value, minVal, maxVal) { + if (minVal !== null && minVal !== undefined) { + value = Math.max(value, minVal); + } + if (maxVal !== null && maxVal !== undefined) { + value = Math.min(value, maxVal); + } + return value; +}; + +Functions.prototype.degreesToRadians = function (deg) { + return deg * (Math.PI / 180); +}; + +Functions.prototype.radiansToDegrees = function (rad) { + return rad / (Math.PI / 180); +}; + +Functions.prototype.intToColorString = function (value) { + /* jslint bitwise: true */ + var trimmedValue = (value & 0xFFFFFF); + var colorStr = trimmedValue.toString(16); + while (colorStr.length < 6) { + colorStr = "0" + colorStr; + } + return '#' + colorStr; +}; + +/** + * + * @param value + * @returns {number|undefined} + */ +Functions.prototype.getIntOrUndefined = function (value) { + if (this.isInt(value)) { + return value; + } else if (value === undefined || value === null) { + return undefined; + } else { + logger.warn("Invalid argument type: " + value); + return undefined; + } +}; + + +/** + * + * @param {string} color + * @param {number} opacity + * @returns {string} + */ +Functions.prototype.colorToRgbaString = function (color, opacity) { + if (color[0] !== '#' || color.length !== 7) { + throw new Error("Expected color in #RRGGBB format, but found: " + color); + } + var red = parseInt(color.substr(1, 2), 16); + var green = parseInt(color.substr(3, 2), 16); + var blue = parseInt(color.substr(5, 2), 16); + var alpha = opacity !== undefined ? opacity : 1.0; + return "rgba(" + red + "," + green + "," + blue + "," + alpha + ")"; +}; + + +/** + * + * @param {LayoutAlias[]|LayoutReaction[]} overlayData + * @returns {Promise<Array>} + */ +Functions.prototype.overlaysToColorDataStructure = function (overlayData) { + var promises = []; + for (var i = 0; i < overlayData.length; i++) { + promises.push(this.overlayToColor(overlayData[i])); + } + return Promise.all(promises).then(function (colors) { + var countByColor = [], color; + for (var i = 0; i < colors.length; i++) { + color = colors[i]; + if (countByColor[color] !== undefined) { + countByColor[color]++; + } else { + countByColor[color] = 1; + } + } + var result = []; + for (color in countByColor) { + if (countByColor.hasOwnProperty(color)) { + result.push({color: color, amount: countByColor[color]}); + } + } + var compare = function (a, b) { + return a.color.localeCompare(b.color); + }; + result.sort(compare); + return result; + }); + +}; + +/** + * Returns stack trace. + * + * @returns {string} stack trace + */ +Functions.prototype.stackTrace = function () { + var err = new Error(); + return err.stack; +}; + +/** + * Returns the position of the element on html page. + * + * @param element + * element for which we want to get the position (top left corner) + * + * @return {Point} coordinates of the element + * + */ +Functions.prototype.getPosition = function (element) { + var xPosition = 0; + var yPosition = 0; + + while (element) { + xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft); + yPosition += (element.offsetTop - element.scrollTop + element.clientTop); + element = element.offsetParent; + } + return new Point(xPosition, yPosition); +}; + +/** + * Checks if the point given as a first argument belongs to a polygon defined as + * a second parameter. Both: point and polygon should use google.map.point + * class. + * + * @param {Point} point + * point which we want to check + * + * @param {Point[]} polygon + * polygon where we check the point + */ + +Functions.prototype.pointInsidePolygon = function (point, polygon) { + var x = point.x; + var y = point.y; + + var inside = false; + for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { + var xi = polygon[i].x, yi = polygon[i].y; + var xj = polygon[j].x, yj = polygon[j].y; + var intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + if (intersect) { + inside = !inside; + } + } + return inside; +}; + +/** + * Returns true if parameter is integer, false otherwise. + * + * @param n + * object to check + */ +Functions.prototype.isInt = function (n) { + return Number(n) === n && n % 1 === 0; +}; + +/** + * Returns true if parameter is a DOM element, false otherwise. + * + * @param o + * object to check + */ +Functions.prototype.isDomElement = function (o) { + if (!o) { + return false; + } + return (typeof HTMLElement === "object" ? o instanceof HTMLElement : // DOM2 + o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string"); +}; + +/** + * + * @param {LayoutAlias|LayoutReaction} elementOverlay + * + * @returns {Promise<string>} + */ + +Functions.prototype.overlayToColor = function (elementOverlay) { + var self = this; + if (elementOverlay === null || elementOverlay === undefined) { + return Promise.reject("elementOverlay cannot be null!"); + } else if (elementOverlay.color !== undefined && elementOverlay.color !== null) { + return Promise.resolve(self.intToColorString(elementOverlay.color.rgb)); + } else { + var ratio = 0; + var promiseColors; + if (elementOverlay.value !== undefined && elementOverlay.value !== null) { + if (elementOverlay.value < 0) { + ratio = -elementOverlay.value; + promiseColors = [ServerConnector.getMinOverlayColorInt(), ServerConnector.getNeutralOverlayColorInt()]; + } else { + ratio = elementOverlay.value; + promiseColors = [ServerConnector.getMaxOverlayColorInt(), ServerConnector.getNeutralOverlayColorInt()]; + } + } else { + ratio = 1; + promiseColors = [ServerConnector.getSimpleOverlayColorInt(), ServerConnector.getNeutralOverlayColorInt()]; + } + + return Promise.all(promiseColors).then(function (colors) { + var maxColor = colors[0]; + var neutralColor = colors[1]; + + ratio = 1 - ratio; + var MAX_RED = 0xFF0000; + var MAX_GREEN = 0x00FF00; + var MAX_BLUE = 0x0000FF; + + var red = maxColor & MAX_RED; + var neutralRed = neutralColor & MAX_RED; + + red = red + (neutralRed - red) * ratio; + red = parseInt(red); + red = red & MAX_RED; + + var green = maxColor & MAX_GREEN; + var neutralGreen = neutralColor & MAX_GREEN; + green = green + (neutralGreen - green) * ratio; + green = parseInt(green); + green = green & MAX_GREEN; + + var blue = maxColor & MAX_BLUE; + var neutralBlue = neutralColor & MAX_BLUE; + blue = blue + (neutralBlue - blue) * ratio; + blue = parseInt(blue); + blue = blue & MAX_BLUE; + + var color = red | green | blue; + return self.intToColorString(color); + }); + } +}; + +Functions.prototype.getElementByName = function (element, name) { + if (element !== undefined) { + if (element.getAttribute("name") === name) { + return element; + } + var children = element.children; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + var res = this.getElementByName(child, name); + if (res !== undefined) { + return res; + } + } + } + return undefined; +}; + + +/** + * + * @param {HTMLElement}element + * @param {string} name class name + * @returns {HTMLElement|undefined} + */ +Functions.prototype.getElementByClassName = function (element, name) { + if (name.indexOf(".") !== 0) { + name = "." + name; + } + return $(name, element)[0]; +}; + +/** + * + * @param {Object} params + * @param {string} params.type type of the {HTMLElement} to be created + * @param {string} [params.inputType] type of the input to be created + * @param {string} [params.className] css class of the element + * @param {string} [params.style] css styling + * @param {string} [params.value] + * @param {string|HTMLElement} [params.content] + * + * @returns {HTMLElement} + */ +Functions.prototype.createElement = function (params) { + var result = document.createElement(params.type); + if (params.id !== null && params.id !== undefined) { + result.id = params.id; + } + if (params.name !== null && params.name !== undefined) { + result.setAttribute("name", params.name); + } + if (params.className !== null && params.className !== undefined) { + result.className = params.className; + } + if (params.inputType !== null && params.inputType !== undefined) { + result.type = params.inputType; + } + if (params.content !== null && params.content !== undefined) { + if (this.isDomElement(params.content)) { + result.appendChild(params.content); + } else if (params.xss !== false) { + var content = xss(params.content); + if (content !== params.content) { + logger.warn("XSS changed content: " + params.content); + } + result.innerHTML = content; + } else { + result.innerHTML = params.content; + } + } + if (params.style !== null && params.style !== undefined) { + result.style.cssText = params.style; + } + if (params.onclick !== null && params.onclick !== undefined) { + result.onclick = params.onclick; + } + if (params.onchange !== null && params.onchange !== undefined) { + result.onchange = params.onchange; + } + if (params.href !== null && params.href !== undefined) { + result.href = params.href; + } + if (params.src !== null && params.src !== undefined) { + result.src = params.src; + } + if (params.value !== null && params.value !== undefined) { + result.value = params.value; + } + if (params.title !== null && params.title !== undefined) { + result.title = params.title; + } + if (params.index !== null && params.index !== undefined) { + result.index = params.index; + } + if (params.data !== null && params.data !== undefined) { + $(result).attr("data", params.data); + } + return result; +}; + +function sqr(x) { + return x * x; +} + +function dist2(v, w) { + return sqr(v.x - w.x) + sqr(v.y - w.y); +} + +function distToSegmentSquared(p, v, w) { + var l2 = dist2(v, w); + + if (l2 === 0) { + return dist2(p, v); + } + + var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2; + + if (t < 0) { + return dist2(p, v); + } + if (t > 1) { + return dist2(p, w); + } + + return dist2(p, new Point(v.x + t * (w.x - v.x), v.y + t * (w.y - v.y))); +} + +Functions.prototype.distance = function (p1, el2) { + if (el2 instanceof Point) { + var p2 = el2; + return Math.sqrt((Math.pow(p1.x - p2.x, 2)) + (Math.pow(p1.y - p2.y, 2))); + } else { + return Math.sqrt(distToSegmentSquared(p1, el2.start, el2.end)); + } +}; + +Functions.prototype.removeChildren = function (element) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } +}; + +/** + * + * @returns {Promise} resolved after javascript is loaded + */ +Functions.prototype.loadScript = function (url) { + return new Promise(function (resolve) { + var scriptExists = false; + var scripts = document.getElementsByTagName('script'); + for (var i = scripts.length; i--;) { + if (scripts[i].src === url) + scriptExists = true; + } + if (!scriptExists) { + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = url; + script.onload = function () { + resolve(); + }; + head.appendChild(script); + } else { + resolve(); + } + }); +}; + +Functions.prototype.computeMD5 = function (s) { + function L(k, d) { + return (k << d) | (k >>> (32 - d)) + } + + function K(G, k) { + var I, d, F, H, x; + F = (G & 2147483648); + H = (k & 2147483648); + I = (G & 1073741824); + d = (k & 1073741824); + x = (G & 1073741823) + (k & 1073741823); + if (I & d) { + return (x ^ 2147483648 ^ F ^ H) + } + if (I | d) { + if (x & 1073741824) { + return (x ^ 3221225472 ^ F ^ H) + } else { + return (x ^ 1073741824 ^ F ^ H) + } + } else { + return (x ^ F ^ H) + } + } + + function r(d, F, k) { + return (d & F) | ((~d) & k) + } + + function q(d, F, k) { + return (d & k) | (F & (~k)) + } + + function p(d, F, k) { + return (d ^ F ^ k) + } + + function n(d, F, k) { + return (F ^ (d | (~k))) + } + + function u(G, F, aa, Z, k, H, I) { + G = K(G, K(K(r(F, aa, Z), k), I)); + return K(L(G, H), F) + } + + function f(G, F, aa, Z, k, H, I) { + G = K(G, K(K(q(F, aa, Z), k), I)); + return K(L(G, H), F) + } + + function D(G, F, aa, Z, k, H, I) { + G = K(G, K(K(p(F, aa, Z), k), I)); + return K(L(G, H), F) + } + + function t(G, F, aa, Z, k, H, I) { + G = K(G, K(K(n(F, aa, Z), k), I)); + return K(L(G, H), F) + } + + function e(G) { + var Z; + var F = G.length; + var x = F + 8; + var k = (x - (x % 64)) / 64; + var I = (k + 1) * 16; + var aa = Array(I - 1); + var d = 0; + var H = 0; + while (H < F) { + Z = (H - (H % 4)) / 4; + d = (H % 4) * 8; + aa[Z] = (aa[Z] | (G.charCodeAt(H) << d)); + H++ + } + Z = (H - (H % 4)) / 4; + d = (H % 4) * 8; + aa[Z] = aa[Z] | (128 << d); + aa[I - 2] = F << 3; + aa[I - 1] = F >>> 29; + return aa + } + + function B(x) { + var k = "", F = "", G, d; + for (d = 0; d <= 3; d++) { + G = (x >>> (d * 8)) & 255; + F = "0" + G.toString(16); + k = k + F.substr(F.length - 2, 2) + } + return k + } + + function J(k) { + k = k.replace(/rn/g, "n"); + var d = ""; + for (var F = 0; F < k.length; F++) { + var x = k.charCodeAt(F); + if (x < 128) { + d += String.fromCharCode(x) + } else { + if ((x > 127) && (x < 2048)) { + d += String.fromCharCode((x >> 6) | 192); + d += String.fromCharCode((x & 63) | 128) + } else { + d += String.fromCharCode((x >> 12) | 224); + d += String.fromCharCode(((x >> 6) & 63) | 128); + d += String.fromCharCode((x & 63) | 128) + } + } + } + return d + } + + var C = Array(); + var P, h, E, v, g, Y, X, W, V; + var S = 7, Q = 12, N = 17, M = 22; + var A = 5, z = 9, y = 14, w = 20; + var o = 4, m = 11, l = 16, j = 23; + var U = 6, T = 10, R = 15, O = 21; + s = J(s); + C = e(s); + Y = 1732584193; + X = 4023233417; + W = 2562383102; + V = 271733878; + for (P = 0; P < C.length; P += 16) { + h = Y; + E = X; + v = W; + g = V; + Y = u(Y, X, W, V, C[P + 0], S, 3614090360); + V = u(V, Y, X, W, C[P + 1], Q, 3905402710); + W = u(W, V, Y, X, C[P + 2], N, 606105819); + X = u(X, W, V, Y, C[P + 3], M, 3250441966); + Y = u(Y, X, W, V, C[P + 4], S, 4118548399); + V = u(V, Y, X, W, C[P + 5], Q, 1200080426); + W = u(W, V, Y, X, C[P + 6], N, 2821735955); + X = u(X, W, V, Y, C[P + 7], M, 4249261313); + Y = u(Y, X, W, V, C[P + 8], S, 1770035416); + V = u(V, Y, X, W, C[P + 9], Q, 2336552879); + W = u(W, V, Y, X, C[P + 10], N, 4294925233); + X = u(X, W, V, Y, C[P + 11], M, 2304563134); + Y = u(Y, X, W, V, C[P + 12], S, 1804603682); + V = u(V, Y, X, W, C[P + 13], Q, 4254626195); + W = u(W, V, Y, X, C[P + 14], N, 2792965006); + X = u(X, W, V, Y, C[P + 15], M, 1236535329); + Y = f(Y, X, W, V, C[P + 1], A, 4129170786); + V = f(V, Y, X, W, C[P + 6], z, 3225465664); + W = f(W, V, Y, X, C[P + 11], y, 643717713); + X = f(X, W, V, Y, C[P + 0], w, 3921069994); + Y = f(Y, X, W, V, C[P + 5], A, 3593408605); + V = f(V, Y, X, W, C[P + 10], z, 38016083); + W = f(W, V, Y, X, C[P + 15], y, 3634488961); + X = f(X, W, V, Y, C[P + 4], w, 3889429448); + Y = f(Y, X, W, V, C[P + 9], A, 568446438); + V = f(V, Y, X, W, C[P + 14], z, 3275163606); + W = f(W, V, Y, X, C[P + 3], y, 4107603335); + X = f(X, W, V, Y, C[P + 8], w, 1163531501); + Y = f(Y, X, W, V, C[P + 13], A, 2850285829); + V = f(V, Y, X, W, C[P + 2], z, 4243563512); + W = f(W, V, Y, X, C[P + 7], y, 1735328473); + X = f(X, W, V, Y, C[P + 12], w, 2368359562); + Y = D(Y, X, W, V, C[P + 5], o, 4294588738); + V = D(V, Y, X, W, C[P + 8], m, 2272392833); + W = D(W, V, Y, X, C[P + 11], l, 1839030562); + X = D(X, W, V, Y, C[P + 14], j, 4259657740); + Y = D(Y, X, W, V, C[P + 1], o, 2763975236); + V = D(V, Y, X, W, C[P + 4], m, 1272893353); + W = D(W, V, Y, X, C[P + 7], l, 4139469664); + X = D(X, W, V, Y, C[P + 10], j, 3200236656); + Y = D(Y, X, W, V, C[P + 13], o, 681279174); + V = D(V, Y, X, W, C[P + 0], m, 3936430074); + W = D(W, V, Y, X, C[P + 3], l, 3572445317); + X = D(X, W, V, Y, C[P + 6], j, 76029189); + Y = D(Y, X, W, V, C[P + 9], o, 3654602809); + V = D(V, Y, X, W, C[P + 12], m, 3873151461); + W = D(W, V, Y, X, C[P + 15], l, 530742520); + X = D(X, W, V, Y, C[P + 2], j, 3299628645); + Y = t(Y, X, W, V, C[P + 0], U, 4096336452); + V = t(V, Y, X, W, C[P + 7], T, 1126891415); + W = t(W, V, Y, X, C[P + 14], R, 2878612391); + X = t(X, W, V, Y, C[P + 5], O, 4237533241); + Y = t(Y, X, W, V, C[P + 12], U, 1700485571); + V = t(V, Y, X, W, C[P + 3], T, 2399980690); + W = t(W, V, Y, X, C[P + 10], R, 4293915773); + X = t(X, W, V, Y, C[P + 1], O, 2240044497); + Y = t(Y, X, W, V, C[P + 8], U, 1873313359); + V = t(V, Y, X, W, C[P + 15], T, 4264355552); + W = t(W, V, Y, X, C[P + 6], R, 2734768916); + X = t(X, W, V, Y, C[P + 13], O, 1309151649); + Y = t(Y, X, W, V, C[P + 4], U, 4149444226); + V = t(V, Y, X, W, C[P + 11], T, 3174756917); + W = t(W, V, Y, X, C[P + 2], R, 718787259); + X = t(X, W, V, Y, C[P + 9], O, 3951481745); + Y = K(Y, h); + X = K(X, E); + W = K(W, v); + V = K(V, g) + } + var i = B(Y) + B(X) + B(W) + B(V); + return i.toLowerCase() +}; + +var singleton = new Functions(); + +module.exports = singleton; diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js index 271aeb78f61889ca31ea9524048fbce63bc14615..977c7f543872ec94e5b2f7f68a7198f987bd5668 100644 --- a/frontend-js/src/main/js/ServerConnector.js +++ b/frontend-js/src/main/js/ServerConnector.js @@ -159,7 +159,7 @@ function isSessionExpiredError(error) { /** * * @param params - * @returns {PromiseLike} + * @returns {PromiseLike|Promise} */ ServerConnector.sendRequest = function (params) { var self = this; @@ -231,6 +231,12 @@ ServerConnector._sendRequest = function (params) { }); }; +/** + * + * @param {string} url + * @param {Object} params + * @returns {Promise} + */ ServerConnector.sendPostRequest = function (url, params) { return this.sendRequest({ method: "POST", @@ -320,8 +326,8 @@ ServerConnector.createGetParams = function (params, prefix) { /** * * @param {Object} paramObj - * @param {string} paramObj.type - * @param {string} [paramObj.url] + * @param {string} [paramObj.type] + * @param {string} paramObj.url * @param {Object} [paramObj.params] * * @returns {string} @@ -1200,8 +1206,13 @@ ServerConnector.updateUser = function (user) { }).then(function (configuration) { return self.updateUserPrivileges({user: user, privileges: user.privilegesToExport(configuration)}); }); - }; + +/** + * + * @param {User} user + * @returns {Promise} + */ ServerConnector.addUser = function (user) { var self = this; var queryParams = { @@ -1219,18 +1230,29 @@ ServerConnector.addUser = function (user) { }).then(function (configuration) { return self.updateUserPrivileges({user: user, privileges: user.privilegesToExport(configuration)}); }); - }; +/** + * + * @param {string} login + * @returns {Promise} + */ ServerConnector.removeUser = function (login) { var self = this; var queryParams = { login: login }; return self.sendDeleteRequest(self.getUserUrl(queryParams)); - }; +/** + * + * @param {Object} params + * @param {User} params.user + * @param {Object} params.privileges + * + * @returns {Promise} + */ ServerConnector.updateUserPrivileges = function (params) { var self = this; var queryParams = { @@ -1253,6 +1275,11 @@ ServerConnector.updateUserPrivileges = function (params) { }); }; +/** + * + * @param {Error} error + * @returns {Promise} + */ ServerConnector.processNetworkError = function (error) { if ((error instanceof NetworkError)) { switch (error.statusCode) { @@ -1268,7 +1295,14 @@ ServerConnector.processNetworkError = function (error) { } }; - +/** + * + * @param {Object} params + * @param {User} params.user + * @param {UserPreferences} params.preferences + * + * @returns {Promise} + */ ServerConnector.updateUserPreferences = function (params) { var self = this; var queryParams = { @@ -1289,6 +1323,12 @@ ServerConnector.updateUserPreferences = function (params) { }); }; +/** + * + * @param {boolean} forceRefresh + * + * @returns {Promise} + */ ServerConnector.getUsers = function (forceRefresh) { var self = this; @@ -1314,6 +1354,10 @@ ServerConnector.getUsers = function (forceRefresh) { } }; +/** + * + * @returns {Promise<Array>} + */ ServerConnector.getReferenceGenomes = function () { var self = this; @@ -1328,7 +1372,15 @@ ServerConnector.getReferenceGenomes = function () { }); }; - +/** + * + * @param {Object} [params] + * @param {string} [params.creator] user login + * @param {boolean} [params.publicOverlay] + * @param {string} [params.projectId] + * + * @returns {Promise<Array>} + */ ServerConnector.getOverlays = function (params) { var self = this; if (params === undefined) { @@ -1353,6 +1405,13 @@ ServerConnector.getOverlays = function (params) { }); }; +/** + * + * @param {number} overlayId + * @param {string} [projectId] + * + * @returns {Promise} + */ ServerConnector.getOverlayElements = function (overlayId, projectId) { var self = this; if (overlayId === undefined) { @@ -1410,6 +1469,11 @@ ServerConnector.getFullOverlayElement = function (params) { }); }; +/** + * + * @param {string} [projectId] + * @returns {Promise} + */ ServerConnector.getProjectId = function (projectId) { var self = this; if (projectId !== undefined && projectId !== null && projectId !== "") { @@ -2154,7 +2218,8 @@ ServerConnector.getReferenceGenome = function (params) { * @param {string|number} params.genomeId * @param {string} params.mappingName * @param {string} params.mappingUrl - * @returns {PromiseLike} + * + * @returns {Promise} */ ServerConnector.addGeneMapping = function (params) { var self = this; @@ -2413,6 +2478,10 @@ ServerConnector.setPluginUserParam = function (params) { }); }; +/** + * + * @returns {Promise} + */ ServerConnector.getSubmapConnections = function () { var self = this; var queryParams = {}; diff --git a/frontend-js/src/main/js/gui/admin/UsersAdminPanel.js b/frontend-js/src/main/js/gui/admin/UsersAdminPanel.js index daf9d1d8e00f59be15a2b5b36b02bb8854106717..1bbc720da8c241f3792adc69edae5d5705e3f409 100644 --- a/frontend-js/src/main/js/gui/admin/UsersAdminPanel.js +++ b/frontend-js/src/main/js/gui/admin/UsersAdminPanel.js @@ -166,11 +166,8 @@ UsersAdminPanel.prototype._createUsersTableRow = function () { var newIsConnected = $('input:checked', field).val() === "LDAP"; var isConnected = user.isConnectedToLdap(); if (isConnected !== newIsConnected) { - console.log(newIsConnected); user.setConnectedToLdap(newIsConnected); return self.getServerConnector().updateUser(user); - } else { - console.log('dont change'); } }).catch(function (error) { GuiConnector.alert(error); diff --git a/frontend-js/src/main/js/map/AbstractCustomMap.js b/frontend-js/src/main/js/map/AbstractCustomMap.js index 967fff2cb0a0ce4e92bdb9664a8decb529c778e7..03f7119a22234b8e84ddcd4af47f08c9e4ce3627 100644 --- a/frontend-js/src/main/js/map/AbstractCustomMap.js +++ b/frontend-js/src/main/js/map/AbstractCustomMap.js @@ -9,6 +9,7 @@ var AliasInfoWindow = require('./window/AliasInfoWindow'); var AliasSurface = require('./surface/AliasSurface'); var GuiConnector = require('../GuiConnector'); var IdentifiedElement = require('./data/IdentifiedElement'); +var LayoutAlias = require('./data/LayoutAlias'); var ObjectWithListeners = require('../ObjectWithListeners'); var MapModel = require('./data/MapModel'); var Point = require('./canvas/Point'); @@ -362,65 +363,127 @@ AbstractCustomMap.prototype._showSelectedDataOverlay = function (overlayId, inde // end ratio var endX = (index + 1) * (1.0 / length); - var overlayAliases; - var overlayReactions; - return self.getProject().getDataOverlayById(overlayId).then(function (overlay) { - overlayAliases = overlay.getAliases(); - overlayReactions = overlay.getReactions(); + return Promise.all([self._showDataOverlayAliases(overlay, startX, endX), + self._showDataOverlayReactions(overlay, length === 1) + ]); + }); +}; - var i, identifiedElements = []; - for (i = 0; i < overlayAliases.length; i++) { - if (overlayAliases[i].getModelId() === self.getId()) { - identifiedElements.push(new IdentifiedElement(overlayAliases[i])); - } +/** + * + * @param {DataOverlay} overlay + * @param {number} startX + * @param {number} endX + * + * @returns {Promise|PromiseLike} + * @private + */ +AbstractCustomMap.prototype._showDataOverlayAliases = function (overlay, startX, endX) { + var self = this; + var overlayAliases = overlay.getAliases(); + var overlayAliasesOnMap = []; + + var i, identifiedElements = []; + var usedAliasIds = []; + var overlayMapIds = []; + for (i = 0; i < overlayAliases.length; i++) { + if (overlayMapIds[overlayAliases[i].getModelId()] === undefined) { + overlayMapIds[overlayAliases[i].getModelId()] = []; } - for (i = 0; i < overlayReactions.length; i++) { - if (overlayReactions[i].getModelId() === self.getId()) { - identifiedElements.push(new IdentifiedElement(overlayReactions[i])); + overlayMapIds[overlayAliases[i].getModelId()].push(overlayAliases[i]); + + if (overlayAliases[i].getModelId() === self.getId()) { + identifiedElements.push(new IdentifiedElement(overlayAliases[i])); + overlayAliasesOnMap.push(overlayAliases[i]); + usedAliasIds[overlayAliases[i].getId()] = true; + } + } + var elementsPointingToSubmapPromises = []; + for (var mapId in overlayMapIds) { + elementsPointingToSubmapPromises.push(self.getProject().getElementsPointingToSubmap(parseInt(mapId))); + } + return Promise.all(elementsPointingToSubmapPromises).then(function (elementsPointingToSubmap) { + for (var i = 0; i < elementsPointingToSubmap.length; i++) { + var row = elementsPointingToSubmap[i]; + for (var j = 0; j < row.length; j++) { + var identifiedElement = row[j]; + if (identifiedElement.getModelId() === self.getId() && !usedAliasIds[identifiedElement.getId()]) { + usedAliasIds[identifiedElement.getId()] = true; + overlayAliasesOnMap.push(new LayoutAlias({ + idObject: identifiedElement.getId(), + modelId: identifiedElement.getModelId(), + value: 0 + })); + } } } - return self.getModel().getByIdentifiedElements(identifiedElements, false); + return self.getModel().getByIdentifiedElements(identifiedElements, false) }).then(function () { - return Promise.each(overlayAliases, function (overlayAlias) { - if (overlayAlias.getModelId() === self.getId()) { - return self.getModel().getAliasById(overlayAlias.getId()).then(function (aliasData) { - var surface = new AliasSurface({ - overlayAlias: overlayAlias, - alias: aliasData, - map: self, - startX: startX, - endX: endX, - onClick: [function () { - return self.getTopMap().getOverlayByName("search").searchByTarget(new IdentifiedElement(aliasData)); - }, function () { - return self.getTopMap().callListeners("onBioEntityClick", new IdentifiedElement(aliasData)); - }] - }); - self.selectedLayoutOverlays[overlayId].push(surface); - return surface.show(); + return Promise.each(overlayAliasesOnMap, function (overlayAlias) { + return self.getModel().getAliasById(overlayAlias.getId()).then(function (aliasData) { + var overlayData; + if (aliasData.getLinkedSubmodelId() !== undefined && overlayMapIds[aliasData.getLinkedSubmodelId()] !== undefined) { + overlayData = overlayMapIds[aliasData.getLinkedSubmodelId()]; + } else { + overlayData = [overlayAlias]; + } + var surface = new AliasSurface({ + overlayData: overlayData, + alias: aliasData, + map: self, + startX: startX, + endX: endX, + onClick: [function () { + return self.getTopMap().getOverlayByName("search").searchByTarget(new IdentifiedElement(aliasData)); + }, function () { + return self.getTopMap().callListeners("onBioEntityClick", new IdentifiedElement(aliasData)); + }] }); - } + self.selectedLayoutOverlays[overlay.getId()].push(surface); + return surface.show(); + }); }); - }).then(function () { - return Promise.each(overlayReactions, function (overlayReaction) { - if (overlayReaction.getModelId() === self.getId()) { - return self.getModel().getReactionById(overlayReaction.getId()).then(function (reactionData) { - var surface = new ReactionSurface({ - layoutReaction: overlayReaction, - reaction: reactionData, - map: self, - onClick: [function () { - return self.getTopMap().getOverlayByName("search").searchByTarget(new IdentifiedElement(reactionData)); - }, function () { - return self.getTopMap().callListeners("onBioEntityClick", new IdentifiedElement(reactionData)); - }], - customized: (length === 1) - }); - self.selectedLayoutOverlays[overlayId].push(surface); - return surface.show(); + }); +}; + +/** + * + * @param {DataOverlay} overlay + * @param {boolean} customized + * + * @returns {Promise} + * @private + */ +AbstractCustomMap.prototype._showDataOverlayReactions = function (overlay, customized) { + var self = this; + var overlayReactions = overlay.getReactions(); + var overlayReactionsOnMap = []; + + var i, identifiedElements = []; + for (i = 0; i < overlayReactions.length; i++) { + if (overlayReactions[i].getModelId() === self.getId()) { + identifiedElements.push(new IdentifiedElement(overlayReactions[i])); + overlayReactionsOnMap.push(overlayReactions[i]); + } + } + return self.getModel().getByIdentifiedElements(identifiedElements, false).then(function () { + return Promise.each(overlayReactionsOnMap, function (overlayReaction) { + return self.getModel().getReactionById(overlayReaction.getId()).then(function (reactionData) { + var surface = new ReactionSurface({ + layoutReaction: overlayReaction, + reaction: reactionData, + map: self, + onClick: [function () { + return self.getTopMap().getOverlayByName("search").searchByTarget(new IdentifiedElement(reactionData)); + }, function () { + return self.getTopMap().callListeners("onBioEntityClick", new IdentifiedElement(reactionData)); + }], + customized: customized }); - } + self.selectedLayoutOverlays[overlay.getId()].push(surface); + return surface.show(); + }); }); }); }; @@ -440,7 +503,7 @@ AbstractCustomMap.prototype._hideSelectedLayout = function (overlayId) { return Promise.resolve(); } - var promises =[]; + var promises = []; for (var i = 0; i < this.selectedLayoutOverlays[overlayId].length; i++) { promises.push(this.selectedLayoutOverlays[overlayId][i].hide()); } @@ -508,27 +571,6 @@ AbstractCustomMap.prototype._openInfoWindowForAlias = function (alias, marker) { } }; -/** - * Returns promise of a list of {@link LayoutAlias} information for a given - * {@link Alias} in all currently visualized overlays. - * - * @param {number} aliasId - * identifier of the {@link Alias} - * @returns {PromiseLike<LayoutAlias[]>| Promise<LayoutAlias[]>} promise of an {Array} with list of {@link LayoutAlias} information - * for a given {@link Alias} in all currently visualized overlays - */ -AbstractCustomMap.prototype.getAliasVisibleLayoutsData = function (aliasId) { - var self = this; - return self.getTopMap().getVisibleDataOverlays().then(function (visibleDataOverlays) { - var result = []; - for (var i = 0; i < visibleDataOverlays.length; i++) { - var overlay = visibleDataOverlays[i]; - result.push(overlay.getFullAliasById(aliasId)); - } - return Promise.all(result); - }); -}; - /** * Opens {@link ReactionInfoWindow} for given reaction identifier. * diff --git a/frontend-js/src/main/js/map/canvas/Bounds.js b/frontend-js/src/main/js/map/canvas/Bounds.js index 210e7484774d27156809bd26498fa32e75cb9352..0cbc6b1f2c88c2616b0248973d5c194bae2bee46 100644 --- a/frontend-js/src/main/js/map/canvas/Bounds.js +++ b/frontend-js/src/main/js/map/canvas/Bounds.js @@ -73,4 +73,16 @@ Bounds.prototype.contains = function (point) { }; +/** + * + * @returns {string} + */ +Bounds.prototype.toString = function () { + if (this._topLeft === undefined) { + return "[NaN]"; + } else { + return "[" + this._topLeft.x + "," + this._topLeft.y + "]-[" + this._rightBottom.x + "," + this._rightBottom.y + "]"; + } +}; + module.exports = Bounds; diff --git a/frontend-js/src/main/js/map/canvas/GoogleMaps/GoogleMapsApiCanvas.js b/frontend-js/src/main/js/map/canvas/GoogleMaps/GoogleMapsApiCanvas.js index 60fb32554f4e23ad3d96ca0f92effd87d5ff3821..2e465b34a8d719c99c9ab9127745803fb3f875e3 100644 --- a/frontend-js/src/main/js/map/canvas/GoogleMaps/GoogleMapsApiCanvas.js +++ b/frontend-js/src/main/js/map/canvas/GoogleMaps/GoogleMapsApiCanvas.js @@ -232,9 +232,9 @@ GoogleMapsApiCanvas.prototype.createMarker = function (options) { /** * * @param {Bounds} options.bounds - * @param {string} options.id - * @param {number} options.fillOpacity * @param {string} options.fillColor + * @param {number} options.fillOpacity + * @param {string} options.id * @param {string} options.strokeColor * @param {number} options.strokeOpacity * @param {number} options.strokeWeight diff --git a/frontend-js/src/main/js/map/canvas/GoogleMaps/GoogleMapsApiRectangle.js b/frontend-js/src/main/js/map/canvas/GoogleMaps/GoogleMapsApiRectangle.js index 97ac9369942a054c256d233fc99e2d10c6ee237a..4490ef861d517ddaf4ce19f58270f3e6fa497c62 100644 --- a/frontend-js/src/main/js/map/canvas/GoogleMaps/GoogleMapsApiRectangle.js +++ b/frontend-js/src/main/js/map/canvas/GoogleMaps/GoogleMapsApiRectangle.js @@ -1,21 +1,23 @@ "use strict"; -var Rectangle = require('../Rectangle'); var Bounds = require('../Bounds'); +var Point = require('../Point'); +var Rectangle = require('../Rectangle'); // noinspection JSUnusedLocalSymbols var logger = require('../../../logger'); /** * - * @param {MapCanvas} options.map + * @param {GoogleMapsApiCanvas} options.map * @param {Bounds} options.bounds - * @param {MapCanvas} options.fillOpacity - * @param {number} options.id - * @param {number} options.strokeWeight - * @param {string} options.fillColor + * @param {string} [options.fillColor] + * @param {{color: string, amount: number}[]} [options.fillGradient] + * @param {number} options.fillOpacity + * @param {string} options.id * @param {string} options.strokeColor * @param {number} options.strokeOpacity + * @param {number} options.strokeWeight * * @constructor * @extends Rectangle @@ -24,24 +26,67 @@ function GoogleMapsApiRectangle(options) { Rectangle.call(this, options); var self = this; + self._rectangles = []; + + + var i; + var bounds; + if (options.fillGradient !== undefined) { + var totalAmount = 0; + for (i = 0; i < options.fillGradient.length; i++) { + totalAmount += options.fillGradient[i].amount; + } + var y = options.bounds.getTopLeft().y; + for (i = 0; i < options.fillGradient.length; i++) { + var x1 = options.bounds.getTopLeft().x; + var x2 = options.bounds.getRightBottom().x; + var y1 = y; + var ratio = options.fillGradient[i].amount / totalAmount; + + var y2 = y1 + ratio * (options.bounds.getRightBottom().y - options.bounds.getTopLeft().y); + y = y2; + bounds = new google.maps.LatLngBounds(); + bounds.extend(self.getMap().fromPointToLatLng(new Point(x1, y1))); + bounds.extend(self.getMap().fromPointToLatLng(new Point(x2, y2))); + self.addGoogleRectangle(new google.maps.Rectangle({ + bounds: bounds, + fillOpacity: options.fillOpacity, + strokeWeight: 0.0, + fillColor: options.fillGradient[i].color + })); + } + bounds = new google.maps.LatLngBounds(); + bounds.extend(self.getMap().fromPointToLatLng(options.bounds.getTopLeft())); + bounds.extend(self.getMap().fromPointToLatLng(options.bounds.getRightBottom())); + self.addGoogleRectangle(new google.maps.Rectangle({ + bounds: bounds, + fillOpacity: 0.0, + id: options.id, + strokeWeight: options.strokeWeight, + strokeColor: options.strokeColor, + strokeOpacity: options.strokeOpacity + })); + } else { + bounds = new google.maps.LatLngBounds(); + bounds.extend(self.getMap().fromPointToLatLng(options.bounds.getTopLeft())); + bounds.extend(self.getMap().fromPointToLatLng(options.bounds.getRightBottom())); + self.addGoogleRectangle(new google.maps.Rectangle({ + bounds: bounds, + fillOpacity: options.fillOpacity, + id: options.id, + strokeWeight: options.strokeWeight, + fillColor: options.fillColor, + strokeColor: options.strokeColor, + strokeOpacity: options.strokeOpacity + })); + } - var bounds = new google.maps.LatLngBounds(); - bounds.extend(this.getMap().fromPointToLatLng(options.bounds.getTopLeft())); - bounds.extend(this.getMap().fromPointToLatLng(options.bounds.getRightBottom())); - - this.setGoogleRectangle(new google.maps.Rectangle({ - bounds: bounds, - fillOpacity: options.fillOpacity, - id: options.id, - strokeWeight: options.strokeWeight, - fillColor: options.fillColor, - strokeColor: options.strokeColor, - strokeOpacity: options.strokeOpacity - })); - - google.maps.event.addListener(this.getGoogleRectangle(), "click", function(){ - return self.callListeners("click"); - }); + var rectangles = self.getGoogleRectangles(); + for (i = 0; i < rectangles.length; i++) { + google.maps.event.addListener(rectangles[i], "click", function () { + return self.callListeners("click"); + }); + } } GoogleMapsApiRectangle.prototype = Object.create(Rectangle.prototype); @@ -51,33 +96,31 @@ GoogleMapsApiRectangle.prototype.constructor = GoogleMapsApiRectangle; * * @param {google.maps.Rectangle} rectangle */ -GoogleMapsApiRectangle.prototype.setGoogleRectangle = function (rectangle) { - this._rectangle = rectangle; +GoogleMapsApiRectangle.prototype.addGoogleRectangle = function (rectangle) { + this._rectangles.push(rectangle); }; /** * - * @returns {google.maps.Rectangle} + * @returns {google.maps.Rectangle[]} */ -GoogleMapsApiRectangle.prototype.getGoogleRectangle = function () { - return this._rectangle; +GoogleMapsApiRectangle.prototype.getGoogleRectangles = function () { + return this._rectangles; }; GoogleMapsApiRectangle.prototype.show = function () { - var googleRectangle = this.getGoogleRectangle(); - if (googleRectangle.getMap() !== undefined && googleRectangle.getMap() !== null) { - logger.warn("Rectangle is already shown"); - } - else { - googleRectangle.setMap(this.getMap().getGoogleMap()); + var rectangles = this.getGoogleRectangles(); + for (var i = 0; i < rectangles.length; i++) { + var rectangle = rectangles[i]; + rectangle.setMap(this.getMap().getGoogleMap()); } }; GoogleMapsApiRectangle.prototype.hide = function () { - if (!this.isShown()) { - logger.warn("Rectangle is already invisible"); - } else { - this.getGoogleRectangle().setMap(null); + var rectangles = this.getGoogleRectangles(); + for (var i = 0; i < rectangles.length; i++) { + var rectangle = rectangles[i]; + rectangle.setMap(null); } }; @@ -86,19 +129,40 @@ GoogleMapsApiRectangle.prototype.hide = function () { * @returns {boolean} */ GoogleMapsApiRectangle.prototype.isShown = function () { - var googleRectangle = this.getGoogleRectangle(); - return googleRectangle.getMap() !== null && googleRectangle.getMap() !== undefined; + var rectangles = this.getGoogleRectangles(); + for (var i = 0; i < rectangles.length; i++) { + var rectangle = rectangles[i]; + if (rectangle.getMap() !== null && rectangle.getMap() !== undefined) { + return true; + } + } + return false; }; /** * - * @param bounds {Bounds} + * @param newBounds {Bounds} */ -GoogleMapsApiRectangle.prototype.setBounds = function (bounds) { - var latLngBounds = new google.maps.LatLngBounds(); - latLngBounds.extend(this.getMap().fromPointToLatLng(bounds.getTopLeft())); - latLngBounds.extend(this.getMap().fromPointToLatLng(bounds.getRightBottom())); - this.getGoogleRectangle().setBounds(latLngBounds); +GoogleMapsApiRectangle.prototype.setBounds = function (newBounds) { + var oldBounds = this.getBounds(); + + var rectangles = this.getGoogleRectangles(); + for (var i = 0; i < rectangles.length; i++) { + var rectangle = rectangles[i]; + var rectangleLatLngBounds = rectangle.getBounds(); + var currentBounds = new Bounds(); + currentBounds.extend(this.getMap().fromLatLngToPoint(rectangleLatLngBounds.getSouthWest())); + currentBounds.extend(this.getMap().fromLatLngToPoint(rectangleLatLngBounds.getNorthEast())); + + var latLngBounds = new google.maps.LatLngBounds(); + + var topLeft = this._transformCoordinates(currentBounds.getTopLeft(), oldBounds, newBounds); + var rightBottom = this._transformCoordinates(currentBounds.getRightBottom(), oldBounds, newBounds); + + latLngBounds.extend(this.getMap().fromPointToLatLng(topLeft)); + latLngBounds.extend(this.getMap().fromPointToLatLng(rightBottom)); + rectangle.setBounds(latLngBounds); + } }; /** @@ -106,10 +170,15 @@ GoogleMapsApiRectangle.prototype.setBounds = function (bounds) { * @returns {Bounds} */ GoogleMapsApiRectangle.prototype.getBounds = function () { - var latLngBounds = this.getGoogleRectangle().getBounds(); var result = new Bounds(); - result.extend(this.getMap().fromLatLngToPoint(latLngBounds.getSouthWest())); - result.extend(this.getMap().fromLatLngToPoint(latLngBounds.getNorthEast())); + + var rectangles = this.getGoogleRectangles(); + for (var i = 0; i < rectangles.length; i++) { + var rectangle = rectangles[i]; + var latLngBounds = rectangle.getBounds(); + result.extend(this.getMap().fromLatLngToPoint(latLngBounds.getSouthWest())); + result.extend(this.getMap().fromLatLngToPoint(latLngBounds.getNorthEast())); + } return result; }; @@ -118,7 +187,11 @@ GoogleMapsApiRectangle.prototype.getBounds = function () { * @param {Object} options */ GoogleMapsApiRectangle.prototype.setOptions = function (options) { - this.getGoogleRectangle().setOptions(options); + var rectangles = this.getGoogleRectangles(); + for (var i = 0; i < rectangles.length; i++) { + var rectangle = rectangles[i]; + rectangle.setOptions(options); + } }; diff --git a/frontend-js/src/main/js/map/canvas/OpenLayers/OpenLayerRectangle.js b/frontend-js/src/main/js/map/canvas/OpenLayers/OpenLayerRectangle.js index eb0b859ee61e9a8156d3eea4eb6e9f2028ae3841..b9037203fc91b3ca670297309d81ca687f3a8839 100644 --- a/frontend-js/src/main/js/map/canvas/OpenLayers/OpenLayerRectangle.js +++ b/frontend-js/src/main/js/map/canvas/OpenLayers/OpenLayerRectangle.js @@ -27,29 +27,84 @@ function OpenLayersRectangle(options) { options.strokeWeight = 1; } this._options = options; + this._rectangles = []; + + if (options.fillGradient !== undefined) { + var totalAmount = 0; + for (var i = 0; i < options.fillGradient.length; i++) { + totalAmount += options.fillGradient[i].amount; + } + var y = options.bounds.getTopLeft().y; + for (i = 0; i < options.fillGradient.length; i++) { + var x1 = options.bounds.getTopLeft().x; + var x2 = options.bounds.getRightBottom().x; + var y1 = y; + var ratio = options.fillGradient[i].amount / totalAmount; + + var y2 = y1 + ratio * (options.bounds.getRightBottom().y - options.bounds.getTopLeft().y); + y = y2; + + var bounds = new Bounds(new Point(x1, y1), new Point(x2, y2)); + + self.addOpenLayersRectangle(self._createFeature({ + strokeWeight: 0.5, + strokeColor: options.fillGradient[i].color, + strokeOpacity: options.fillOpacity, + bounds: bounds, + fillOpacity: options.fillOpacity, + fillColor: options.fillGradient[i].color, + source: options.source + })); + } + self.addOpenLayersRectangle(self._createFeature({ + strokeWeight: options.strokeWeight, + strokeColor: options.strokeColor, + strokeOpacity: options.strokeOpacity, + bounds: options.bounds, + fillOpacity: 0.0, + id: options.id, + fillColor: "#000000", + source: options.source + })); + } else { + self.addOpenLayersRectangle(self._createFeature(options)); + } - var style = self.createStyle(options); +} + +OpenLayersRectangle.prototype = Object.create(Rectangle.prototype); +OpenLayersRectangle.prototype.constructor = OpenLayersRectangle; - var polygon = this.createPolygon(options.bounds); +OpenLayersRectangle.prototype._createFeature = function (options) { + var self = this; + var style = self.createStyle(options); + var polygon; + polygon = self.createPolygon(options.bounds); var feature = new ol.Feature({ geometry: polygon, id: options.id }); - this.setOpenLayersRectangle(feature); feature.setStyle(new ol.style.Style({})); options.source.addFeature(feature); feature.__openLayerRectangle = this; + /** + * + * @type {style.Style} + * @private + */ + feature.__style = style; + return feature; +}; - this._style = style; - -} - -OpenLayersRectangle.prototype = Object.create(Rectangle.prototype); -OpenLayersRectangle.prototype.constructor = OpenLayersRectangle; +/** + * + * @param {Bounds} bounds + * @returns {geom.Polygon} + */ OpenLayersRectangle.prototype.createPolygon = function (bounds) { var self = this; @@ -68,6 +123,16 @@ OpenLayersRectangle.prototype.createPolygon = function (bounds) { return new ol.geom.Polygon([points]); }; +/** + * + * @param {string} options.strokeColor + * @param {number} options.strokeOpacity + * @param {number} options.strokeWeight + * @param {string} options.fillColor + * @param {number} options.fillOpacity + * + * @returns {style.Style} + */ OpenLayersRectangle.prototype.createStyle = function (options) { return new ol.style.Style({ stroke: new ol.style.Stroke({ @@ -80,54 +145,110 @@ OpenLayersRectangle.prototype.createStyle = function (options) { }); }; - -OpenLayersRectangle.prototype.setOpenLayersRectangle = function (rectangle) { - this._rectangle = rectangle; +OpenLayersRectangle.prototype.addOpenLayersRectangle = function (rectangle) { + this._rectangles.push(rectangle); }; -OpenLayersRectangle.prototype.getOpenLayersRectangle = function () { - return this._rectangle; +/** + * + * @returns {Array} + */ +OpenLayersRectangle.prototype.getOpenLayersRectangles = function () { + return this._rectangles; }; +/** + * + */ OpenLayersRectangle.prototype.show = function () { - return this.getOpenLayersRectangle().setStyle(this._style); + var rectangles = this.getOpenLayersRectangles(); + + for (var i = 0; i < rectangles.length; i++) { + var rectangle = rectangles[i]; + rectangle.setStyle(rectangle.__style); + } }; OpenLayersRectangle.prototype.hide = function () { - return this.getOpenLayersRectangle().setStyle(new ol.style.Style({})); + var rectangles = this.getOpenLayersRectangles(); + var hiddenStyle = new ol.style.Style({}); + for (var i = 0; i < rectangles.length; i++) { + var rectangle = rectangles[i]; + rectangle.setStyle(hiddenStyle); + } }; OpenLayersRectangle.prototype.isShown = function () { - return this.getOpenLayersRectangle().getStyle().getFill() !== null; + var rectangles = this.getOpenLayersRectangles(); + for (var i = 0; i < rectangles.length; i++) { + var rectangle = rectangles[i]; + if (rectangle.getStyle().getFill() !== null) { + return true; + } + } }; /** * - * @param bounds {Bounds} + * @param newBounds {Bounds} */ -OpenLayersRectangle.prototype.setBounds = function (bounds) { - this._options.bounds = bounds; - this.getOpenLayersRectangle().setGeometry(this.createPolygon(bounds)); +OpenLayersRectangle.prototype.setBounds = function (newBounds) { + var self = this; + + self._options.bounds = newBounds; + var oldBounds = self.getBounds(); + + var rectangles = self.getOpenLayersRectangles(); + + for (var i = 0; i < rectangles.length; i++) { + var rectangle = rectangles[i]; + var currentBounds = new Bounds(); + var extent = rectangle.getGeometry().getExtent(); + + var projection1 = [extent[0], extent[1]]; + currentBounds.extend(self.getMap().fromProjectionToPoint(projection1)); + var projection2 = [extent[2], extent[3]]; + currentBounds.extend(self.getMap().fromProjectionToPoint(projection2)); + + var topLeft = self._transformCoordinates(currentBounds.getTopLeft(), oldBounds, newBounds); + var rightBottom = self._transformCoordinates(currentBounds.getRightBottom(), oldBounds, newBounds); + + rectangle.setGeometry(self.createPolygon(new Bounds(topLeft, rightBottom))); + } + }; OpenLayersRectangle.prototype.getBounds = function () { var self = this; - var extent = self.getOpenLayersRectangle().getGeometry().getExtent(); - - var projection1 = [extent[0], extent[1]]; - var p1 = self.getMap().fromProjectionToPoint(projection1); - var projection2 = [extent[2], extent[3]]; - var p2 = self.getMap().fromProjectionToPoint(projection2); - return new Bounds(p1, p2); + var bounds = new Bounds(); + var rectangles = this.getOpenLayersRectangles(); + for (var i = 0; i < rectangles.length; i++) { + var rectangle = rectangles[i]; + var extent = rectangle.getGeometry().getExtent(); + + var projection1 = [extent[0], extent[1]]; + bounds.extend(self.getMap().fromProjectionToPoint(projection1)); + var projection2 = [extent[2], extent[3]]; + bounds.extend(self.getMap().fromProjectionToPoint(projection2)); + } + return bounds; }; OpenLayersRectangle.prototype.setOptions = function (options) { var self = this; self._options = Object.assign(self._options, options); - var style = self.createStyle(self._options); - if (self.isShown()) { - self.getOpenLayersRectangle().setStyle(style); + var rectangles = this.getOpenLayersRectangles(); + for (var i = 0; i < rectangles.length; i++) { + var rectangle = rectangles[i]; + var style = rectangle.__style; + if (self._options.fillColor !== undefined) { + style.getFill().setColor(Functions.colorToRgbaString(self._options.fillColor, self._options.fillOpacity)); + } + + if (i === rectangles.length - 1) { + style.getStroke().setWidth(self._options.strokeWeight); + style.getStroke().setColor(Functions.colorToRgbaString(self._options.strokeColor, self._options.strokeOpacity)); + } } - self._style = style; }; module.exports = OpenLayersRectangle; diff --git a/frontend-js/src/main/js/map/canvas/Point.js b/frontend-js/src/main/js/map/canvas/Point.js index ae53c3343776760b0b4fd26e9809bec824d4ff5d..a579d014ffb342eecdf01f587fc056a9d93dc511 100644 --- a/frontend-js/src/main/js/map/canvas/Point.js +++ b/frontend-js/src/main/js/map/canvas/Point.js @@ -22,4 +22,13 @@ function Point(x, y) { } } +/** + * + * @param {Point} otherPoint + * @returns {number} + */ +Point.prototype.distanceTo = function (otherPoint) { + return Math.sqrt((otherPoint.x - this.x) * (otherPoint.x - this.x) + (otherPoint.y - this.y) * (otherPoint.y - this.y)); +}; + module.exports = Point; diff --git a/frontend-js/src/main/js/map/canvas/Rectangle.js b/frontend-js/src/main/js/map/canvas/Rectangle.js index b30ec9c9ea811cd02685665975a8009a7a960260..9da655253c42dc1842b7902122b70d50ea0f67da 100644 --- a/frontend-js/src/main/js/map/canvas/Rectangle.js +++ b/frontend-js/src/main/js/map/canvas/Rectangle.js @@ -1,6 +1,7 @@ "use strict"; var MapCanvas = require('./MapCanvas'); +var Point = require('./Point'); // noinspection JSUnusedLocalSymbols var logger = require('../../logger'); @@ -74,4 +75,19 @@ Rectangle.prototype.getMap = function () { return this._map; }; +/** + * + * @param {Point} point + * @param {Bounds} oldBounds + * @param {Bounds} newBounds + * + * @returns {Point} + * @protected + */ +Rectangle.prototype._transformCoordinates = function (point, oldBounds, newBounds) { + var x = newBounds.getTopLeft().x + (point.x - oldBounds.getTopLeft().x) / (oldBounds.getRightBottom().x - oldBounds.getTopLeft().x) * (newBounds.getRightBottom().x - newBounds.getTopLeft().x); + var y = newBounds.getTopLeft().y + (point.y - oldBounds.getTopLeft().y) / (oldBounds.getRightBottom().y - oldBounds.getTopLeft().y) * (newBounds.getRightBottom().y - newBounds.getTopLeft().y); + return new Point(x, y); +}; + module.exports = Rectangle; diff --git a/frontend-js/src/main/js/map/data/Alias.js b/frontend-js/src/main/js/map/data/Alias.js index ad5aa080b4bf5b4ecc3dcd2b428b11e66277f62b..1bfd76989315b1d645d6a6438a4fad8556fbe213 100644 --- a/frontend-js/src/main/js/map/data/Alias.js +++ b/frontend-js/src/main/js/map/data/Alias.js @@ -26,6 +26,7 @@ function Alias(javaObject) { this.setWidth(javaObject.bounds.width); this.setHeight(javaObject.bounds.height); } + this.setLinkedSubmodelId(javaObject.linkedSubmodel); if (this._modelId === undefined) { throw new Error("ModelId is not defined for alias" + javaObject); diff --git a/frontend-js/src/main/js/map/data/LayoutAlias.js b/frontend-js/src/main/js/map/data/LayoutAlias.js index 5f39c3089cb33e44cc5ae7c77c6385f5a424f4d9..e82336b0ce6f72c0e25549a5a4bb2367ec430ee8 100644 --- a/frontend-js/src/main/js/map/data/LayoutAlias.js +++ b/frontend-js/src/main/js/map/data/LayoutAlias.js @@ -1,111 +1,116 @@ -"use strict"; - -var GeneVariant = require('./GeneVariant'); - -/** - * Class representing alias visualized in a overlay. - * - * @param javaObject - * object de-serialized ajax query to the server side - */ -function LayoutAlias(javaObject) { - this.setId(javaObject.idObject); - this.setValue(javaObject.value); - this.setColor(javaObject.color); - this.setModelId(javaObject.modelId); - this.setDescription(javaObject.description); - if (javaObject.type === undefined) { - this.setType(LayoutAlias.LIGHT); - } else if (javaObject.type === LayoutAlias.GENETIC_VARIANT) { - this.setType(LayoutAlias.GENETIC_VARIANT); - } else if (javaObject.type === LayoutAlias.GENERIC) { - this.setType(LayoutAlias.GENERIC); - } else { - throw new Error("Unknown type: " + javaObject.type); - } - - this.setGeneVariants([]); - if (javaObject.geneVariations !== undefined) { - for (var i = 0; i < javaObject.geneVariations.length; i++) { - this.addGeneVariant(new GeneVariant(javaObject.geneVariations[i])); - } - } -} - -LayoutAlias.LIGHT = "LIGHT"; -LayoutAlias.GENETIC_VARIANT = "GENETIC_VARIANT"; -LayoutAlias.GENERIC = "GENERIC"; - -LayoutAlias.prototype.getId = function () { - return this.id; -}; - -LayoutAlias.prototype.setId = function (id) { - this.id = parseInt(id); -}; - -LayoutAlias.prototype.getModelId = function () { - return this._modelId; -}; - -LayoutAlias.prototype.setModelId = function (modelId) { - this._modelId = parseInt(modelId); -}; - -LayoutAlias.prototype.getValue = function () { - return this.value; -}; - -LayoutAlias.prototype.getColor = function () { - return this.color; -}; - -LayoutAlias.prototype.getType = function () { - return this._type; -}; - -LayoutAlias.prototype.getGeneVariants = function () { - return this._geneVariants; -}; - -LayoutAlias.prototype.setValue = function (newValue) { - this.value = newValue; -}; - -LayoutAlias.prototype.setColor = function (newColor) { - this.color = newColor; -}; - -LayoutAlias.prototype.setType = function (newType) { - this._type = newType; -}; - -LayoutAlias.prototype.setGeneVariants = function (newGeneVariants) { - this._geneVariants = newGeneVariants; -}; - -LayoutAlias.prototype.update = function (alias) { - if (!(alias instanceof LayoutAlias)) { - throw new Error("Unknown parameter type: " + alias); - } - - this.setValue(alias.getValue()); - this.setColor(alias.getColor()); - this.setGeneVariants(alias.getGeneVariants()); - this.setType(alias.getType()); - this.setDescription(alias.getDescription()); -}; - -LayoutAlias.prototype.addGeneVariant = function (geneVariant) { - this._geneVariants.push(geneVariant); -}; - -LayoutAlias.prototype.getDescription = function () { - return this._description; -}; - -LayoutAlias.prototype.setDescription = function (description) { - this._description = description; -}; - -module.exports = LayoutAlias; +"use strict"; + +var GeneVariant = require('./GeneVariant'); + +/** + * Class representing alias visualized in a overlay. + * + * @param {number} javaObject.idObject + * @param {number} [javaObject.value] + * @param {string} [javaObject.color] + * @param {number} javaObject.modelId + * @param {string} [javaObject.description] + * @param {string} [javaObject.type=LayoutAlias.LIGHT] + * @param {Array} [javaObject.geneVariations] + */ +function LayoutAlias(javaObject) { + this.setId(javaObject.idObject); + this.setValue(javaObject.value); + this.setColor(javaObject.color); + this.setModelId(javaObject.modelId); + this.setDescription(javaObject.description); + if (javaObject.type === undefined) { + this.setType(LayoutAlias.LIGHT); + } else if (javaObject.type === LayoutAlias.GENETIC_VARIANT) { + this.setType(LayoutAlias.GENETIC_VARIANT); + } else if (javaObject.type === LayoutAlias.GENERIC) { + this.setType(LayoutAlias.GENERIC); + } else { + throw new Error("Unknown type: " + javaObject.type); + } + + this.setGeneVariants([]); + if (javaObject.geneVariations !== undefined) { + for (var i = 0; i < javaObject.geneVariations.length; i++) { + this.addGeneVariant(new GeneVariant(javaObject.geneVariations[i])); + } + } +} + +LayoutAlias.LIGHT = "LIGHT"; +LayoutAlias.GENETIC_VARIANT = "GENETIC_VARIANT"; +LayoutAlias.GENERIC = "GENERIC"; + +LayoutAlias.prototype.getId = function () { + return this.id; +}; + +LayoutAlias.prototype.setId = function (id) { + this.id = parseInt(id); +}; + +LayoutAlias.prototype.getModelId = function () { + return this._modelId; +}; + +LayoutAlias.prototype.setModelId = function (modelId) { + this._modelId = parseInt(modelId); +}; + +LayoutAlias.prototype.getValue = function () { + return this.value; +}; + +LayoutAlias.prototype.getColor = function () { + return this.color; +}; + +LayoutAlias.prototype.getType = function () { + return this._type; +}; + +LayoutAlias.prototype.getGeneVariants = function () { + return this._geneVariants; +}; + +LayoutAlias.prototype.setValue = function (newValue) { + this.value = newValue; +}; + +LayoutAlias.prototype.setColor = function (newColor) { + this.color = newColor; +}; + +LayoutAlias.prototype.setType = function (newType) { + this._type = newType; +}; + +LayoutAlias.prototype.setGeneVariants = function (newGeneVariants) { + this._geneVariants = newGeneVariants; +}; + +LayoutAlias.prototype.update = function (alias) { + if (!(alias instanceof LayoutAlias)) { + throw new Error("Unknown parameter type: " + alias); + } + + this.setValue(alias.getValue()); + this.setColor(alias.getColor()); + this.setGeneVariants(alias.getGeneVariants()); + this.setType(alias.getType()); + this.setDescription(alias.getDescription()); +}; + +LayoutAlias.prototype.addGeneVariant = function (geneVariant) { + this._geneVariants.push(geneVariant); +}; + +LayoutAlias.prototype.getDescription = function () { + return this._description; +}; + +LayoutAlias.prototype.setDescription = function (description) { + this._description = description; +}; + +module.exports = LayoutAlias; diff --git a/frontend-js/src/main/js/map/data/MapModel.js b/frontend-js/src/main/js/map/data/MapModel.js index 81a5dae53e5580ab0fa912bd3b7df2be7257ad81..2173114711ad26566674abb7edb539d4d5d8f0c3 100644 --- a/frontend-js/src/main/js/map/data/MapModel.js +++ b/frontend-js/src/main/js/map/data/MapModel.js @@ -256,7 +256,7 @@ MapModel.prototype.getMissingElements = function (elements) { } else { aliasPromise = ServerConnector.getAliases({ ids: aliasIds, - columns: "id,bounds,modelId" + columns: "id,bounds,modelId,linkedSubmodel" }); } diff --git a/frontend-js/src/main/js/map/surface/AliasSurface.js b/frontend-js/src/main/js/map/surface/AliasSurface.js index f7dc2968bc2c47f7f20d80ad3847b9fc11c9ecdc..b80391ef416accf3cd996390e639767efd78f6d5 100644 --- a/frontend-js/src/main/js/map/surface/AliasSurface.js +++ b/frontend-js/src/main/js/map/surface/AliasSurface.js @@ -1,260 +1,291 @@ -"use strict"; - -/* exported logger */ - -// noinspection JSUnusedLocalSymbols -var logger = require('../../logger'); -var functions = require('../../Functions'); - -var AbstractSurfaceElement = require('./AbstractSurfaceElement'); -var ConfigurationType = require('../../ConfigurationType'); -var IdentifiedElement = require('../data/IdentifiedElement'); -var Bounds = require('../canvas/Bounds'); -var Point = require('../canvas/Point'); - -/** - * Class representing overlay of the alias on the map relevant for a specific - * layout. - * - * @param {LayoutAlias} [params.overlayAlias] - {@link LayoutAlias} for which overlay is created - * @param {number} [params.startX] - this is the ratio on OX axis that should be use as a - * starting point of the overlay. For instance when there are three - * overlays to visualize then - * <ul> - * <li>the first layout have startX=0.0; endX=0.33333</li> - * <li>second layout have startX=0.33333; endX=0.66666</li> - * <li>the last layout have startX=0.66666; endX=1.0</li> - * </ul> - * @param {number} [params.endX] this is the ratio on OX axis that should be use as a - * starting point of the overlay - - * @param {IdentifiedElement} [params.element] - * @param {Alias} params.alias - * @param {AbstractCustomMap} params.map - * @param {function|function[]} [params.onClick] - * @constructor - * @extends AbstractSurfaceElement - */ -function AliasSurface(params) { - // call super constructor - AbstractSurfaceElement.call(this, params); - - this.setOverlayData(params.overlayAlias); - this.setStartX(params.startX); - this.setEndX(params.endX); - - this.setColor(params.color); - this.setFillOpacity(params.opacity); - this.setStrokeWeight(params.strokeWeight); - this.setStrokeColor(params.strokeColor); - this.setStrokeOpacity(params.strokeOpacity); - - // original data - this.setBioEntity(params.alias); - this.setIdentifiedElement(new IdentifiedElement(params.alias)); -} - -AliasSurface.prototype = Object.create(AbstractSurfaceElement.prototype); -AliasSurface.prototype.constructor = AliasSurface; - -/** - * - * @param {string} color - */ -AliasSurface.prototype.setColor = function (color) { - if (color === undefined) { - color = "#FF0000"; - } - - this._color = color; - var mapCanvasObjects = this.getMapCanvasObjects(); - for (var i = 0; i < mapCanvasObjects.length; i++) { - mapCanvasObjects[i].setOptions({ - strokeColor: color - }); - } -}; - -/** - * - * @param {number} opacity - */ -AliasSurface.prototype.setFillOpacity = function (opacity) { - this._fillOpacity = opacity; -}; - -/** - * - * @returns {number|undefined} - */ -AliasSurface.prototype.getFillOpacity = function () { - return this._fillOpacity; -}; - -/** - * - * @param {number} weight - */ -AliasSurface.prototype.setStrokeWeight = function (weight) { - if (weight === undefined) { - weight = 1; - } - this._strokeWeight = weight; -}; - -/** - * - * @returns {number} - */ -AliasSurface.prototype.getStrokeWeight = function () { - return this._strokeWeight; -}; - -/** - * - * @param {string} color - */ -AliasSurface.prototype.setStrokeColor = function (color) { - if (color === undefined) { - color = "#000000"; - } - this._strokeColor = color; -}; - -/** - * - * @returns {string} - */ -AliasSurface.prototype.getStrokeColor = function () { - return this._strokeColor; -}; - -/** - * - * @param {number} opacity - */ -AliasSurface.prototype.setStrokeOpacity = function (opacity) { - if (opacity === undefined) { - opacity = 1; - } - this._strokeOpacity = opacity; -}; - -AliasSurface.prototype.getStrokeOpacity = function () { - return this._strokeOpacity; -}; - -/** - * Function used to recalculate boundaries of the {@link AliasSurface}. - * Boundaries define how big part of original alias is taken by this layout - * visualization. - * - * @param {number} startX - * value between 0..1 defining where should be the start on OX axis - * @param {number} endX - * value between 0..1 defining where should be the end on OX axis - */ -AliasSurface.prototype.setBoundsForAlias = function (startX, endX) { - var alias = this.getBioEntity(); - var pointA = new Point(alias.getX() + startX * alias.getWidth(), alias.getY()); - var pointB = new Point(alias.getX() + endX * alias.getWidth(), alias.getY() + alias.getHeight()); - - var bounds = new Bounds(pointA, pointB); - this.getMapCanvasObjects()[0].setBounds(bounds); -}; - -/** - * - * @returns {PromiseLike<any>} - */ -AliasSurface.prototype.init = function () { - var self = this; - var overlayData = self.getOverlayData(); - var alias = self.getBioEntity(); - var map = self.getCustomMap(); - var startX = self.getStartX(); - var endX = self.getEndX(); - - var pointA = new Point(alias.getX() + startX * alias.getWidth(), alias.getY()); - var pointB = new Point(alias.getX() + endX * alias.getWidth(), alias.getY() + alias.getHeight()); - - var bounds = new Bounds(pointA, pointB); - var fillOpacity; - return ServerConnector.getConfigurationParam(ConfigurationType.OVERLAY_OPACITY).then(function (result) { - fillOpacity = self.getFillOpacity(); - if (fillOpacity === undefined) { - fillOpacity = result; - } - if (overlayData !== undefined) { - return functions.overlayToColor(overlayData); - } else { - return "#FF0000"; - } - }).then(function (color) { - self.addMapCanvasObject(map.getMapCanvas().createRectangle({ - fillOpacity: fillOpacity, - strokeColor: self.getStrokeColor(), - strokeOpacity: self.getStrokeOpacity(), - strokeWeight: self.getStrokeWeight(), - fillColor: color, - bounds: bounds - })); - }); -}; - -/** - * - * @returns {LayoutAlias} - */ -AliasSurface.prototype.getOverlayData = function () { - return this._overlayData; -}; - -/** - * - * @param {LayoutAlias} overlayData - */ -AliasSurface.prototype.setOverlayData = function (overlayData) { - this._overlayData = overlayData; -}; - -/** - * - * @returns {number} - */ -AliasSurface.prototype.getStartX = function () { - return this._startX; -}; - -/** - * - * @param {number} startX - */ -AliasSurface.prototype.setStartX = function (startX) { - if (startX === undefined) { - startX = 0; - } - this._startX = startX; -}; - -/** - * - * @returns {number} - */ -AliasSurface.prototype.getEndX = function () { - return this._endX; -}; - -/** - * - * @param {number} endX - */ -AliasSurface.prototype.setEndX = function (endX) { - if (endX === undefined) { - endX = 1; - } - this._endX = endX; -}; - - -module.exports = AliasSurface; +"use strict"; + +/* exported logger */ + +// noinspection JSUnusedLocalSymbols +var logger = require('../../logger'); +var functions = require('../../Functions'); + +var AbstractSurfaceElement = require('./AbstractSurfaceElement'); +var ConfigurationType = require('../../ConfigurationType'); +var IdentifiedElement = require('../data/IdentifiedElement'); +var Bounds = require('../canvas/Bounds'); +var Point = require('../canvas/Point'); + +/** + * Class representing overlay of the alias on the map relevant for a specific + * layout. + * + * @param {LayoutAlias[]} [params.overlayData] - {@link LayoutAlias} for which overlay is created + * @param {number} [params.startX] - this is the ratio on OX axis that should be use as a + * starting point of the overlay. For instance when there are three + * overlays to visualize then + * <ul> + * <li>the first layout have startX=0.0; endX=0.33333</li> + * <li>second layout have startX=0.33333; endX=0.66666</li> + * <li>the last layout have startX=0.66666; endX=1.0</li> + * </ul> + * @param {number} [params.endX] this is the ratio on OX axis that should be use as a + * starting point of the overlay + + * @param {IdentifiedElement} [params.element] + * @param {Alias} params.alias + * @param {AbstractCustomMap} params.map + * @param {function|function[]} [params.onClick] + * @constructor + * @extends AbstractSurfaceElement + */ +function AliasSurface(params) { + // call super constructor + AbstractSurfaceElement.call(this, params); + if (params.overlayAlias !== undefined) { + throw new Error(); + } + + this.setOverlayData(params.overlayData); + this.setStartX(params.startX); + this.setEndX(params.endX); + + this.setColor(params.color); + this.setFillOpacity(params.opacity); + this.setStrokeWeight(params.strokeWeight); + this.setStrokeColor(params.strokeColor); + this.setStrokeOpacity(params.strokeOpacity); + + // original data + this.setBioEntity(params.alias); + this.setIdentifiedElement(new IdentifiedElement(params.alias)); +} + +AliasSurface.prototype = Object.create(AbstractSurfaceElement.prototype); +AliasSurface.prototype.constructor = AliasSurface; + +/** + * + * @param {string} color + */ +AliasSurface.prototype.setColor = function (color) { + if (color === undefined) { + color = "#FF0000"; + } + + this._color = color; + var mapCanvasObjects = this.getMapCanvasObjects(); + for (var i = 0; i < mapCanvasObjects.length; i++) { + mapCanvasObjects[i].setOptions({ + strokeColor: color + }); + } +}; + +/** + * + * @returns {string} + */ +AliasSurface.prototype.getColor = function () { + return this._color; +}; + +/** + * + * @param {number} opacity + */ +AliasSurface.prototype.setFillOpacity = function (opacity) { + this._fillOpacity = opacity; +}; + +/** + * + * @returns {number|undefined} + */ +AliasSurface.prototype.getFillOpacity = function () { + return this._fillOpacity; +}; + +/** + * + * @param {number} weight + */ +AliasSurface.prototype.setStrokeWeight = function (weight) { + if (weight === undefined) { + weight = 1; + } + this._strokeWeight = weight; +}; + +/** + * + * @returns {number} + */ +AliasSurface.prototype.getStrokeWeight = function () { + return this._strokeWeight; +}; + +/** + * + * @param {string} color + */ +AliasSurface.prototype.setStrokeColor = function (color) { + if (color === undefined) { + color = "#000000"; + } + this._strokeColor = color; +}; + +/** + * + * @returns {string} + */ +AliasSurface.prototype.getStrokeColor = function () { + return this._strokeColor; +}; + +/** + * + * @param {number} opacity + */ +AliasSurface.prototype.setStrokeOpacity = function (opacity) { + if (opacity === undefined) { + opacity = 1; + } + this._strokeOpacity = opacity; +}; + +/** + * + * @returns {number} + */ +AliasSurface.prototype.getStrokeOpacity = function () { + return this._strokeOpacity; +}; + +/** + * Function used to recalculate boundaries of the {@link AliasSurface}. + * Boundaries define how big part of original alias is taken by this layout + * visualization. + * + * @param {number} startX + * value between 0..1 defining where should be the start on OX axis + * @param {number} endX + * value between 0..1 defining where should be the end on OX axis + */ +AliasSurface.prototype.setBoundsForAlias = function (startX, endX) { + var alias = this.getBioEntity(); + var pointA = new Point(alias.getX() + startX * alias.getWidth(), alias.getY()); + var pointB = new Point(alias.getX() + endX * alias.getWidth(), alias.getY() + alias.getHeight()); + + var bounds = new Bounds(pointA, pointB); + this.getMapCanvasObjects()[0].setBounds(bounds); +}; + +AliasSurface.prototype._computeColors = function () { + var self = this; + var overlayData = self.getOverlayData(); + if (overlayData === undefined || overlayData.length === 0) { + return self.getColor(); + } else { + return functions.overlaysToColorDataStructure(overlayData); + } + +}; +/** + * + * @returns {PromiseLike<any>} + */ +AliasSurface.prototype.init = function () { + var self = this; + var alias = self.getBioEntity(); + var map = self.getCustomMap(); + var startX = self.getStartX(); + var endX = self.getEndX(); + + var pointA = new Point(alias.getX() + startX * alias.getWidth(), alias.getY()); + var pointB = new Point(alias.getX() + endX * alias.getWidth(), alias.getY() + alias.getHeight()); + + var bounds = new Bounds(pointA, pointB); + var fillOpacity; + return map.getServerConnector().getConfigurationParam(ConfigurationType.OVERLAY_OPACITY).then(function (result) { + fillOpacity = self.getFillOpacity(); + if (fillOpacity === undefined) { + fillOpacity = result; + } + return self._computeColors(); + }).then(function (color) { + if (typeof color === 'string' || color instanceof String) { + self.addMapCanvasObject(map.getMapCanvas().createRectangle({ + fillOpacity: fillOpacity, + strokeColor: self.getStrokeColor(), + strokeOpacity: self.getStrokeOpacity(), + strokeWeight: self.getStrokeWeight(), + fillColor: color, + bounds: bounds + })); + } else { + self.addMapCanvasObject(map.getMapCanvas().createRectangle({ + fillOpacity: fillOpacity, + strokeColor: self.getStrokeColor(), + strokeOpacity: self.getStrokeOpacity(), + strokeWeight: self.getStrokeWeight(), + fillGradient: color, + bounds: bounds + })); + } + }); +}; + +/** + * + * @returns {LayoutAlias[]} + */ +AliasSurface.prototype.getOverlayData = function () { + return this._overlayData; +}; + +/** + * + * @param {LayoutAlias[]} overlayData + */ +AliasSurface.prototype.setOverlayData = function (overlayData) { + this._overlayData = overlayData; +}; + +/** + * + * @returns {number} + */ +AliasSurface.prototype.getStartX = function () { + return this._startX; +}; + +/** + * + * @param {number} startX + */ +AliasSurface.prototype.setStartX = function (startX) { + if (startX === undefined) { + startX = 0; + } + this._startX = startX; +}; + +/** + * + * @returns {number} + */ +AliasSurface.prototype.getEndX = function () { + return this._endX; +}; + +/** + * + * @param {number} endX + */ +AliasSurface.prototype.setEndX = function (endX) { + if (endX === undefined) { + endX = 1; + } + this._endX = endX; +}; + + +module.exports = AliasSurface; diff --git a/frontend-js/src/main/js/map/window/AbstractInfoWindow.js b/frontend-js/src/main/js/map/window/AbstractInfoWindow.js index c174f946a93fbf7a57590a1c94d5a0e60b53f37e..63a91ad29070633a007e64f983e726c8df451051 100644 --- a/frontend-js/src/main/js/map/window/AbstractInfoWindow.js +++ b/frontend-js/src/main/js/map/window/AbstractInfoWindow.js @@ -1,743 +1,743 @@ -"use strict"; - -var Promise = require("bluebird"); - -var logger = require('../../logger'); -var Functions = require('../../Functions'); - -var Comment = require('../data/Comment'); -var GuiConnector = require('../../GuiConnector'); -var GuiUtils = require('../../gui/leftPanel/GuiUtils'); -var IdentifiedElement = require('../data/IdentifiedElement'); -var ObjectWithListeners = require('../../ObjectWithListeners'); -var TargettingStructure = require('../data/TargettingStructure'); - -/** - * Class representing any info window in our map. - * - * @param {IdentifiedElement} params.identifiedElement - * @param {AbstractCustomMap} params.map - * @param {Marker} params.marker - * - * @constructor - */ -function AbstractInfoWindow(params) { - // call super constructor - ObjectWithListeners.call(this); - - var self = this; - - self.setIdentifiedElement(params.identifiedElement); - - self.setCustomMap(params.map); - self.setMarker(params.marker); - - self.setContent(this.createWaitingContentDiv()); - - self._overlayFullView = []; - - self.registerPropertyType("overlayFullView"); - - self.registerListenerType("onShow"); - self.registerListenerType("onUpdate"); - - self.setGuiUtils(new GuiUtils()); - - var dbOverlaySearchChanged = function () { - return self.update(); - }; - var searchDbOverlay = params.map.getTopMap().getOverlayByName("search"); - if (searchDbOverlay !== undefined) { - searchDbOverlay.addListener("onSearch", dbOverlaySearchChanged); - } - var commentDbOverlay = params.map.getTopMap().getOverlayByName("comment"); - if (commentDbOverlay !== undefined) { - commentDbOverlay.addListener("onSearch", dbOverlaySearchChanged); - } -} - -AbstractInfoWindow.prototype = Object.create(ObjectWithListeners.prototype); -AbstractInfoWindow.prototype.constructor = AbstractInfoWindow; - -/** - * Returns <code>true</code> if overlay should visualize all possible values. - * - * @param {string} overlayName - * name of the overlay - * @returns {boolean}, <code>true</code> if overlay should visualize all possible values - */ -AbstractInfoWindow.prototype.isOverlayFullView = function (overlayName) { - if (this._overlayFullView[overlayName] === undefined) { - this._overlayFullView[overlayName] = false; - } - return this._overlayFullView[overlayName]; -}; - -/** - * Returns associative array with information if specific overlay should present - * all possible results or only specified by the data searched by user. - * - * @returns {Object.<string,boolean>} with information if specific overlay should present all - * possible results or only specified by the data searched by user - */ -AbstractInfoWindow.prototype.getOverlayFullViewArray = function () { - return this._overlayFullView; -}; - -/** - * - * @param {string} overlayName - * @param {boolean} value - * @returns {Promise} - */ -AbstractInfoWindow.prototype.setOverlayFullView = function (overlayName, value) { - var oldVal = this._overlayFullView[overlayName]; - this._overlayFullView[overlayName] = value; - if (oldVal !== value) { - return this.firePropertyChangeListener("overlayFullView", overlayName + "," + oldVal, value); - } else { - return Promise.resolve(); - } -}; - -/** - * This method checks if {@link AbstractInfoWindow} is opened. - * - * @returns {Boolean} <code>true</code> if window is opened, - * <code>false</code> otherwise - */ -AbstractInfoWindow.prototype.isOpened = function () { - if (this._infoWindow === undefined) { - return false; - } - return this._infoWindow.isOpened(); -}; - -/** - * Opens Info Window. - * - * @param {Marker} [newMarker] - * - * @returns {PromiseLike<any> | Promise<any>} - */ -AbstractInfoWindow.prototype.open = function (newMarker) { - var self = this; - var infoWindow = self._infoWindow; - if (infoWindow === null || infoWindow === undefined) { - logger.warn("Cannot open window."); - return Promise.resolve(); - } - if (newMarker !== undefined) { - infoWindow.setMarker(newMarker); - } - infoWindow.open(); - - return self.update().then(function () { - return self.callListeners("onShow"); - }); -}; - -/** - * Sets new content of the info window. - * - * @param {HTMLElement|string} content - * new content of the window - */ -AbstractInfoWindow.prototype.setContent = function (content) { - var self = this; - self._content = content; - if (self._infoWindow !== undefined) { - self._infoWindow.setContent(content); - } -}; - -/** - * Returns content visualized in the info window. - * - * @returns {string|HTMLElement} content visualized in the info window - */ -AbstractInfoWindow.prototype.getContent = function () { - return this._content; -}; - -/** - * Creates div for an overlay data. - * - * @param {AbstractDbOverlay} overlay - * corresponding overlay - * @param {BioEntity[]|Comment[]|Drug[]|MiRna[]|Chemical[]} data - * data taken from overlay - * @returns {HTMLElement} div for given overlay data - */ -AbstractInfoWindow.prototype.createOverlayInfoDiv = function (overlay, data) { - var alias = this.alias; - if (alias !== undefined) { - if (alias.getType() !== undefined) { - if (overlay.name === "drug") { - if (alias.getType().toUpperCase() === "RNA" || // - alias.getType().toUpperCase() === "PROTEIN" || // - alias.getType().toUpperCase() === "GENE") { - return this._createDrugInfoDiv(overlay, data); - } else { - return null; - } - } else if (overlay.name === "chemical") { - if (this.alias.getType().toUpperCase() === "RNA" || // - alias.getType().toUpperCase() === "PROTEIN" || // - alias.getType().toUpperCase() === "GENE") { - return this._createChemicalInfoDiv(overlay, data); - } else { - return null; - } - } else if (overlay.name === "mirna") { - if (alias.getType().toUpperCase() === "RNA" || // - alias.getType().toUpperCase() === "PROTEIN" || // - alias.getType().toUpperCase() === "GENE") { - return this._createMiRnaInfoDiv(overlay, data); - } else { - return null; - } - - } else if (overlay.name === "comment") { - return this._createCommentInfoDiv(overlay, data); - } else { - logger.warn("Unknown overlay data for AliasInfoWindow: " + overlay.name); - return this._createDefaultInfoDiv(overlay, data); - } - } else { - logger.debug(alias); - throw new Error("Cannot customize info window. Alias type is unknown "); - } - } else { - if (overlay.getName() === "comment") { - return this._createCommentInfoDiv(overlay, data); - } else { - logger.debug("Cannot customize info window. Alias not defined. Overlay: " + overlay.getName()); - return null; - } - } -}; - -/** - * Creates and returns div for drug overlay information. - * - * @param {AbstractDbOverlay} overlay - * @param {Drug[]} data - * data taken from drug overlay - * @returns {HTMLElement} div for drug overlay information - * @private - */ -AbstractInfoWindow.prototype._createDrugInfoDiv = function (overlay, data) { - return this._createTargetInfoDiv({ - overlay: overlay, - data: data, - name: "Interacting drugs" - }); -}; - -/** - * Creates and returns div for comment overlay information. - * - * @param {AbstractDbOverlay} overlay - * @param {Comment[]} data - * data taken from comment overlay - * @returns {HTMLElement} div for comment overlay information - */ -AbstractInfoWindow.prototype._createCommentInfoDiv = function (overlay, data) { - if (data.length === 0 || data[0] === undefined) { - return null; - } - var result = document.createElement("div"); - - var titleElement = document.createElement("h3"); - titleElement.innerHTML = "Comments"; - result.appendChild(titleElement); - for (var i = 0; i < data.length; i++) { - var comment = data[i]; - if (comment instanceof Comment) { - if (!comment.isRemoved()) { - result.appendChild(document.createElement("hr")); - var commentId = document.createElement("div"); - commentId.innerHTML = '#' + comment.getId(); - result.appendChild(commentId); - result.appendChild(document.createElement("br")); - var commentContent = Functions.createElement({type: "div", content: comment.getContent(), xss: true}); - - result.appendChild(commentContent); - } - } else { - throw new Error("Invalid comment data: " + comment); - } - } - - return result; -}; - -/** - * Creates and returns div for unknown overlay. - * - * @param {AbstractDbOverlay} overlay - * @param {Array} data - * data taken from overlay - * @returns {HTMLElement} div for overlay information - */ - -AbstractInfoWindow.prototype._createDefaultInfoDiv = function (overlay, data) { - var divElement = document.createElement("div"); - var count = 0; - - var titleElement = document.createElement("h3"); - var title = document.createTextNode(overlay.getName()); - titleElement.appendChild(title); - divElement.appendChild(titleElement); - for (var searchId in data) { - if (data.hasOwnProperty(searchId) && data[searchId] !== undefined && data[searchId] !== null) { - count++; - var resultTitleElement = document.createElement("h4"); - var resultTitle = document.createTextNode(searchId); - resultTitleElement.appendChild(resultTitle); - divElement.appendChild(resultTitleElement); - - var keys = Object.keys(data[searchId]); - for (var i = 0; i < keys.length; i++) { - var resultValElement = document.createElement("p"); - var resultVal = document.createTextNode(keys[i] + ": " + data[searchId][keys[i]]); - resultValElement.appendChild(resultVal); - divElement.appendChild(resultValElement); - } - } - } - - if (count === 0) { - divElement = null; - } - return divElement; -}; - -/** - * Returns Marker object where this info window is attached. - * - * @returns {Marker} object where this info window is attached - */ -AbstractInfoWindow.prototype.getMarker = function () { - return this._marker; -}; - -/** - * - * @param {Marker} marker - */ -AbstractInfoWindow.prototype.setMarker = function (marker) { - this._marker = marker; - if (this._infoWindow !== undefined) { - this._infoWindow.setMarker(marker); - } -}; - -/** - * Returns {@link AbstractCustomMap} where this window is presented. - * - * @returns {AbstractCustomMap} where this window is presented - */ -AbstractInfoWindow.prototype.getCustomMap = function () { - return this.customMap; -}; - -/** - * - * @param {AbstractCustomMap} map - */ -AbstractInfoWindow.prototype.setCustomMap = function (map) { - if (map === undefined) { - throw new Error("Map must be defined"); - } - this.customMap = map; -}; - -/** - * Returns html DOM object with content that should presented when waiting for - * some data from server. - * - * @returns {HTMLElement} html with content that should presented when waiting for - * some data from server - */ -AbstractInfoWindow.prototype.createWaitingContentDiv = function () { - var result = document.createElement("div"); - var img = document.createElement("img"); - img.src = GuiConnector.getImgPrefix() + GuiConnector.getLoadingImg(); - var message = document.createElement("h4"); - message.innerHTML = "loading..."; - result.appendChild(img); - result.appendChild(message); - return result; -}; - -/** - * This is a generic method that updates content of the window. - * - * @returns {Promise|PromiseLike} - * @private - */ -AbstractInfoWindow.prototype._updateContent = function () { - var contentDiv = null; - var self = this; - - if (!self.isOpened()) { - return Promise.resolve(); - } else { - self.setContent(self.createWaitingContentDiv()); - - return self.createContentDiv().then(function (content) { - contentDiv = content; - return self.createOverlaysDiv(); - }).then(function (overlaysDiv) { - if (overlaysDiv !== undefined && overlaysDiv !== null) { - contentDiv.appendChild(overlaysDiv); - } - self.setContent(contentDiv); - return self.callListeners("onUpdate"); - }).then(function () { - return contentDiv; - }); - } -}; - -/** - * Creates and returns div with overlays content. - * - * @returns {Promise<HTMLElement>} with html representing data taken from - * {@link AbstractDbOverlay} for this window - */ -AbstractInfoWindow.prototype.createOverlaysDiv = function () { - var self = this; - var result = document.createElement("div"); - return this.getOverlaysData(self.getOverlayFullViewArray()).then(function (overlayData) { - for (var i = 0; i < overlayData.length; i++) { - var overlay = overlayData[i].overlay; - var data = overlayData[i].data; - var overlayInfo = self.createOverlayInfoDiv(overlay, data); - if (overlayInfo !== null) { - result.appendChild(overlayInfo); - } - } - return result; - }); -}; - -// noinspection JSUnusedLocalSymbols -/** - * Returns array with data taken from all known {@link AbstractDbOverlay}. - * - * @param {Object.<string,boolean>} general - * if true then all elements will be returned, if false then only ones - * available right now in the overlay - * - * @returns {Promise} array with data from {@link AbstractDbOverlay} - */ -AbstractInfoWindow.prototype.getOverlaysData = function (general) { - throw new Error("Not implemented"); -}; - -/** - * Abstract method (to be implemented by subclasses) for updating content. - * - * @returns {Promise} - */ -AbstractInfoWindow.prototype.update = function () { - return this._updateContent(); -}; - -/** - * - * @param {string} params.name - * @param {AbstractDbOverlay} params.overlay - * @param {Array} params.data - * @returns {HTMLElement} - * @private - */ -AbstractInfoWindow.prototype._createTargetInfoDiv = function (params) { - var overlay = params.overlay; - var data = params.data; - var name = params.name; - - var self = this; - var result = document.createElement("div"); - - var titleElement = document.createElement("h3"); - titleElement.innerHTML = name; - result.appendChild(titleElement); - if (overlay.allowGeneralSearch()) { - var checkboxDiv = document.createElement("div"); - checkboxDiv.style.float = "right"; - - var checkbox = document.createElement("input"); - checkbox.id = "checkbox-" + name + "-" + this.getElementType() + "-" + this.getElementId(); - checkbox.type = "checkbox"; - checkbox.checked = self.isOverlayFullView(overlay.getName()); - checkbox.onclick = function () { - return self.setOverlayFullView(overlay.getName(), this.checked).then(null, GuiConnector.alert); - }; - - checkboxDiv.appendChild(checkbox); - - var description = document.createElement("div"); - description.style.float = "right"; - description.innerHTML = "Show all"; - checkboxDiv.appendChild(description); - result.appendChild(checkboxDiv); - } - var count = 0; - for (var dataId in data) { - if (data.hasOwnProperty(dataId)) { - count++; - } - } - - var table = self._createTableForTargetDiv(data, overlay); - - if (count === 0 && !overlay.allowGeneralSearch() && !this.isOverlayFullView(overlay.getName())) { - result = null; - } - if (result !== null) { - result.appendChild(table); - } - return result; -}; - -/** - * - * @param {Array} data - * @param {AbstractDbOverlay} overlay - * @returns {HTMLElement} - * @private - */ -AbstractInfoWindow.prototype._createTableForTargetDiv = function (data, overlay) { - var self = this; - var table = document.createElement("table"); - table.className = "minerva-window-drug-table"; - var header = document.createElement("tr"); - var headerCol = document.createElement("th"); - headerCol.innerHTML = "Name"; - header.appendChild(headerCol); - headerCol = document.createElement("th"); - headerCol.innerHTML = "References"; - header.appendChild(headerCol); - - var cell; - table.appendChild(header); - var row; - - var onclick = function () { - // ';' enforces single query (in case there are ',' characters in the name) - return overlay.searchByQuery(this.innerHTML + ";"); - }; - - var count = 0; - for (var searchId in data) { - if (data.hasOwnProperty(searchId)) { - - row = document.createElement("tr"); - var nameContent = searchId; - var annotations = []; - if (typeof data[searchId] === "string") { - nameContent = data[searchId]; - } else if (data[searchId] instanceof TargettingStructure) { - nameContent = data[searchId].getName(); - var targets = data[searchId].getTargetsForIdentifiedElement(self.getIdentifiedElement()); - for (var i = 0; i < targets.length; i++) { - var references = targets[i].getReferences(); - for (var j = 0; j < references.length; j++) { - annotations.push(references[j]); - } - } - } - var link = Functions.createElement({ - type: "a", - onclick: onclick, - href: "#", - content: nameContent - }); - - var nameTd = Functions.createElement({ - type: "td" - }); - nameTd.appendChild(link); - row.appendChild(nameTd); - - var referencesCell = Functions.createElement({ - type: "td" - }); - referencesCell.appendChild(self.getGuiUtils().createAnnotationList(annotations, {groupAnnotations: false})); - - row.appendChild(referencesCell); - - table.appendChild(row); - count++; - } - } - - if (self.isOverlayFullView(overlay.getName()) && count === 0) { - row = document.createElement("tr"); - cell = document.createElement("td"); - cell.colSpan = 2; - cell.innerHTML = "No results available"; - row.appendChild(cell); - table.appendChild(row); - } - - if (!self.isOverlayFullView(overlay.getName()) && count === 0 && overlay.allowGeneralSearch()) { - row = document.createElement("tr"); - cell = document.createElement("td"); - cell.colSpan = 2; - cell.innerHTML = "Search for available targets"; - row.appendChild(cell); - table.appendChild(row); - } - return table; -}; - -/** - * - * @returns {PromiseLike<any> | Promise<any>} - */ -AbstractInfoWindow.prototype.init = function () { - var self = this; - var promises = [ - // default settings of visualizing full information about elements - this.setOverlayFullView("drug", false), - this.setOverlayFullView("chemical", false), - this.setOverlayFullView("mirna", false), - this.setOverlayFullView("search", false), - // only all comments should be visible from the beginning - this.setOverlayFullView("comment", true) - ]; - - return Promise.all(promises).then(function () { - // listener called when user want to see all data about specific data overlay - var onOverlayFullViewChanged = function (e) { - var self = e.object; - // first change the content of the element - return self.update().then(function () { - if (e.newVal) { - var element = new IdentifiedElement({ - objectId: self.getElementId(), - modelId: self.getCustomMap().getId(), - type: self.getElementType() - }); - var topMap = self.getCustomMap().getTopMap(); - return topMap.retrieveOverlayDetailDataForElement(element, self.getOverlayFullViewArray()); - } - }); - - }; - - self.addPropertyChangeListener("overlayFullView", onOverlayFullViewChanged); - - self._infoWindow = self.getCustomMap().getMapCanvas().createInfoWindow({ - content: self.content, - position: self.getPosition(), - marker: self._marker - }); - - return ServerConnector.getConfiguration(); - }).then(function (configuration) { - self.getGuiUtils().setConfiguration(configuration); - self.getGuiUtils().setMap(self.getCustomMap()); - }); -}; - -/** - * - * @param {GuiUtils} guiUtils - */ -AbstractInfoWindow.prototype.setGuiUtils = function (guiUtils) { - this._guiUtils = guiUtils; -}; - -/** - * - * @returns {GuiUtils} - */ -AbstractInfoWindow.prototype.getGuiUtils = function () { - return this._guiUtils; -}; - -/** - * Creates and returns DOM div for chemical overlay information. - * - * @param {AbstractDbOverlay} overlay - * @param {Chemical[]} data - * data taken from chemical overlay - * @returns {HTMLElement} element with a div for comment overlay information - * @private - */ -AbstractInfoWindow.prototype._createChemicalInfoDiv = function (overlay, data) { - return this._createTargetInfoDiv({ - overlay: overlay, - data: data, - name: "Interacting chemicals" - }); -}; - -/** - * Creates and returns DOM div for mi rna overlay information. - * - * @param {AbstractDbOverlay} overlay - * @param {MiRna[]} data - * data taken from mi rna overlay - * @returns {HTMLElement} DOM element with a div for comment overlay information - */ -AbstractInfoWindow.prototype._createMiRnaInfoDiv = function (overlay, data) { - return this._createTargetInfoDiv({ - overlay: overlay, - data: data, - name: "Interacting Micro RNAs" - }); -}; - -/** - * - * @param {IdentifiedElement} identifiedElement - */ -AbstractInfoWindow.prototype.setIdentifiedElement = function (identifiedElement) { - if (identifiedElement === undefined) { - throw new Error("identifiedElement cannot be undefined"); - } - this._identifiedElement = identifiedElement; -}; - -/** - * - * @returns {IdentifiedElement} - */ -AbstractInfoWindow.prototype.getIdentifiedElement = function () { - return this._identifiedElement; -}; - - -/** - * Method returning identifier of the object for which this window was created. - * - * @returns {string|number} - */ -AbstractInfoWindow.prototype.getElementId = function () { - return this.getIdentifiedElement().getId(); -}; - -/** - * Method returning type of the object for which this window was created. - * - * @returns {string} - */ -AbstractInfoWindow.prototype.getElementType = function () { - return this.getIdentifiedElement().getType(); -}; - -/** - * @returns {Point} - */ -AbstractInfoWindow.prototype.getPosition = function () { - throw new Error("Not Implemented"); -}; - -module.exports = AbstractInfoWindow; +"use strict"; + +var Promise = require("bluebird"); + +var logger = require('../../logger'); +var Functions = require('../../Functions'); + +var Comment = require('../data/Comment'); +var GuiConnector = require('../../GuiConnector'); +var GuiUtils = require('../../gui/leftPanel/GuiUtils'); +var IdentifiedElement = require('../data/IdentifiedElement'); +var ObjectWithListeners = require('../../ObjectWithListeners'); +var TargettingStructure = require('../data/TargettingStructure'); + +/** + * Class representing any info window in our map. + * + * @param {IdentifiedElement} params.identifiedElement + * @param {AbstractCustomMap} params.map + * @param {Marker} params.marker + * + * @constructor + */ +function AbstractInfoWindow(params) { + // call super constructor + ObjectWithListeners.call(this); + + var self = this; + + self.setIdentifiedElement(params.identifiedElement); + + self.setCustomMap(params.map); + self.setMarker(params.marker); + + self.setContent(this.createWaitingContentDiv()); + + self._overlayFullView = []; + + self.registerPropertyType("overlayFullView"); + + self.registerListenerType("onShow"); + self.registerListenerType("onUpdate"); + + self.setGuiUtils(new GuiUtils()); + + var dbOverlaySearchChanged = function () { + return self.update(); + }; + var searchDbOverlay = params.map.getTopMap().getOverlayByName("search"); + if (searchDbOverlay !== undefined) { + searchDbOverlay.addListener("onSearch", dbOverlaySearchChanged); + } + var commentDbOverlay = params.map.getTopMap().getOverlayByName("comment"); + if (commentDbOverlay !== undefined) { + commentDbOverlay.addListener("onSearch", dbOverlaySearchChanged); + } +} + +AbstractInfoWindow.prototype = Object.create(ObjectWithListeners.prototype); +AbstractInfoWindow.prototype.constructor = AbstractInfoWindow; + +/** + * Returns <code>true</code> if overlay should visualize all possible values. + * + * @param {string} overlayName + * name of the overlay + * @returns {boolean}, <code>true</code> if overlay should visualize all possible values + */ +AbstractInfoWindow.prototype.isOverlayFullView = function (overlayName) { + if (this._overlayFullView[overlayName] === undefined) { + this._overlayFullView[overlayName] = false; + } + return this._overlayFullView[overlayName]; +}; + +/** + * Returns associative array with information if specific overlay should present + * all possible results or only specified by the data searched by user. + * + * @returns {Object.<string,boolean>} with information if specific overlay should present all + * possible results or only specified by the data searched by user + */ +AbstractInfoWindow.prototype.getOverlayFullViewArray = function () { + return this._overlayFullView; +}; + +/** + * + * @param {string} overlayName + * @param {boolean} value + * @returns {Promise} + */ +AbstractInfoWindow.prototype.setOverlayFullView = function (overlayName, value) { + var oldVal = this._overlayFullView[overlayName]; + this._overlayFullView[overlayName] = value; + if (oldVal !== value) { + return this.firePropertyChangeListener("overlayFullView", overlayName + "," + oldVal, value); + } else { + return Promise.resolve(); + } +}; + +/** + * This method checks if {@link AbstractInfoWindow} is opened. + * + * @returns {Boolean} <code>true</code> if window is opened, + * <code>false</code> otherwise + */ +AbstractInfoWindow.prototype.isOpened = function () { + if (this._infoWindow === undefined) { + return false; + } + return this._infoWindow.isOpened(); +}; + +/** + * Opens Info Window. + * + * @param {Marker} [newMarker] + * + * @returns {PromiseLike<any> | Promise<any>} + */ +AbstractInfoWindow.prototype.open = function (newMarker) { + var self = this; + var infoWindow = self._infoWindow; + if (infoWindow === null || infoWindow === undefined) { + logger.warn("Cannot open window."); + return Promise.resolve(); + } + if (newMarker !== undefined) { + infoWindow.setMarker(newMarker); + } + infoWindow.open(); + + return self.update().then(function () { + return self.callListeners("onShow"); + }); +}; + +/** + * Sets new content of the info window. + * + * @param {HTMLElement|string} content + * new content of the window + */ +AbstractInfoWindow.prototype.setContent = function (content) { + var self = this; + self._content = content; + if (self._infoWindow !== undefined) { + self._infoWindow.setContent(content); + } +}; + +/** + * Returns content visualized in the info window. + * + * @returns {string|HTMLElement} content visualized in the info window + */ +AbstractInfoWindow.prototype.getContent = function () { + return this._content; +}; + +/** + * Creates div for an overlay data. + * + * @param {AbstractDbOverlay} overlay + * corresponding overlay + * @param {BioEntity[]|Comment[]|Drug[]|MiRna[]|Chemical[]} data + * data taken from overlay + * @returns {HTMLElement} div for given overlay data + */ +AbstractInfoWindow.prototype.createOverlayInfoDiv = function (overlay, data) { + var alias = this.alias; + if (alias !== undefined) { + if (alias.getType() !== undefined) { + if (overlay.name === "drug") { + if (alias.getType().toUpperCase() === "RNA" || // + alias.getType().toUpperCase() === "PROTEIN" || // + alias.getType().toUpperCase() === "GENE") { + return this._createDrugInfoDiv(overlay, data); + } else { + return null; + } + } else if (overlay.name === "chemical") { + if (this.alias.getType().toUpperCase() === "RNA" || // + alias.getType().toUpperCase() === "PROTEIN" || // + alias.getType().toUpperCase() === "GENE") { + return this._createChemicalInfoDiv(overlay, data); + } else { + return null; + } + } else if (overlay.name === "mirna") { + if (alias.getType().toUpperCase() === "RNA" || // + alias.getType().toUpperCase() === "PROTEIN" || // + alias.getType().toUpperCase() === "GENE") { + return this._createMiRnaInfoDiv(overlay, data); + } else { + return null; + } + + } else if (overlay.name === "comment") { + return this._createCommentInfoDiv(overlay, data); + } else { + logger.warn("Unknown overlay data for AliasInfoWindow: " + overlay.name); + return this._createDefaultInfoDiv(overlay, data); + } + } else { + logger.debug(alias); + throw new Error("Cannot customize info window. Alias type is unknown "); + } + } else { + if (overlay.getName() === "comment") { + return this._createCommentInfoDiv(overlay, data); + } else { + logger.debug("Cannot customize info window. Alias not defined. Overlay: " + overlay.getName()); + return null; + } + } +}; + +/** + * Creates and returns div for drug overlay information. + * + * @param {AbstractDbOverlay} overlay + * @param {Drug[]} data + * data taken from drug overlay + * @returns {HTMLElement} div for drug overlay information + * @private + */ +AbstractInfoWindow.prototype._createDrugInfoDiv = function (overlay, data) { + return this._createTargetInfoDiv({ + overlay: overlay, + data: data, + name: "Interacting drugs" + }); +}; + +/** + * Creates and returns div for comment overlay information. + * + * @param {AbstractDbOverlay} overlay + * @param {Comment[]} data + * data taken from comment overlay + * @returns {HTMLElement} div for comment overlay information + */ +AbstractInfoWindow.prototype._createCommentInfoDiv = function (overlay, data) { + if (data.length === 0 || data[0] === undefined) { + return null; + } + var result = document.createElement("div"); + + var titleElement = document.createElement("h3"); + titleElement.innerHTML = "Comments"; + result.appendChild(titleElement); + for (var i = 0; i < data.length; i++) { + var comment = data[i]; + if (comment instanceof Comment) { + if (!comment.isRemoved()) { + result.appendChild(document.createElement("hr")); + var commentId = document.createElement("div"); + commentId.innerHTML = '#' + comment.getId(); + result.appendChild(commentId); + result.appendChild(document.createElement("br")); + var commentContent = Functions.createElement({type: "div", content: comment.getContent(), xss: true}); + + result.appendChild(commentContent); + } + } else { + throw new Error("Invalid comment data: " + comment); + } + } + + return result; +}; + +/** + * Creates and returns div for unknown overlay. + * + * @param {AbstractDbOverlay} overlay + * @param {Array} data + * data taken from overlay + * @returns {HTMLElement} div for overlay information + */ + +AbstractInfoWindow.prototype._createDefaultInfoDiv = function (overlay, data) { + var divElement = document.createElement("div"); + var count = 0; + + var titleElement = document.createElement("h3"); + var title = document.createTextNode(overlay.getName()); + titleElement.appendChild(title); + divElement.appendChild(titleElement); + for (var searchId in data) { + if (data.hasOwnProperty(searchId) && data[searchId] !== undefined && data[searchId] !== null) { + count++; + var resultTitleElement = document.createElement("h4"); + var resultTitle = document.createTextNode(searchId); + resultTitleElement.appendChild(resultTitle); + divElement.appendChild(resultTitleElement); + + var keys = Object.keys(data[searchId]); + for (var i = 0; i < keys.length; i++) { + var resultValElement = document.createElement("p"); + var resultVal = document.createTextNode(keys[i] + ": " + data[searchId][keys[i]]); + resultValElement.appendChild(resultVal); + divElement.appendChild(resultValElement); + } + } + } + + if (count === 0) { + divElement = null; + } + return divElement; +}; + +/** + * Returns Marker object where this info window is attached. + * + * @returns {Marker} object where this info window is attached + */ +AbstractInfoWindow.prototype.getMarker = function () { + return this._marker; +}; + +/** + * + * @param {Marker} marker + */ +AbstractInfoWindow.prototype.setMarker = function (marker) { + this._marker = marker; + if (this._infoWindow !== undefined) { + this._infoWindow.setMarker(marker); + } +}; + +/** + * Returns {@link AbstractCustomMap} where this window is presented. + * + * @returns {AbstractCustomMap} where this window is presented + */ +AbstractInfoWindow.prototype.getCustomMap = function () { + return this.customMap; +}; + +/** + * + * @param {AbstractCustomMap} map + */ +AbstractInfoWindow.prototype.setCustomMap = function (map) { + if (map === undefined) { + throw new Error("Map must be defined"); + } + this.customMap = map; +}; + +/** + * Returns html DOM object with content that should presented when waiting for + * some data from server. + * + * @returns {HTMLElement} html with content that should presented when waiting for + * some data from server + */ +AbstractInfoWindow.prototype.createWaitingContentDiv = function () { + var result = document.createElement("div"); + var img = document.createElement("img"); + img.src = GuiConnector.getImgPrefix() + GuiConnector.getLoadingImg(); + var message = document.createElement("h4"); + message.innerHTML = "loading..."; + result.appendChild(img); + result.appendChild(message); + return result; +}; + +/** + * This is a generic method that updates content of the window. + * + * @returns {Promise|PromiseLike} + * @private + */ +AbstractInfoWindow.prototype._updateContent = function () { + var contentDiv = null; + var self = this; + + if (!self.isOpened()) { + return Promise.resolve(); + } else { + self.setContent(self.createWaitingContentDiv()); + + return self.createContentDiv().then(function (content) { + contentDiv = content; + return self.createDbOverlaysDiv(); + }).then(function (overlaysDiv) { + if (overlaysDiv !== undefined && overlaysDiv !== null) { + contentDiv.appendChild(overlaysDiv); + } + self.setContent(contentDiv); + return self.callListeners("onUpdate"); + }).then(function () { + return contentDiv; + }); + } +}; + +/** + * Creates and returns div with overlays content. + * + * @returns {Promise<HTMLElement>} with html representing data taken from + * {@link AbstractDbOverlay} for this window + */ +AbstractInfoWindow.prototype.createDbOverlaysDiv = function () { + var self = this; + var result = document.createElement("div"); + return this.getDbOverlaysData(self.getOverlayFullViewArray()).then(function (overlayData) { + for (var i = 0; i < overlayData.length; i++) { + var overlay = overlayData[i].overlay; + var data = overlayData[i].data; + var overlayInfo = self.createOverlayInfoDiv(overlay, data); + if (overlayInfo !== null) { + result.appendChild(overlayInfo); + } + } + return result; + }); +}; + +// noinspection JSUnusedLocalSymbols +/** + * Returns array with data taken from all known {@link AbstractDbOverlay}. + * + * @param {Object.<string,boolean>} general + * if true then all elements will be returned, if false then only ones + * available right now in the overlay + * + * @returns {Promise} array with data from {@link AbstractDbOverlay} + */ +AbstractInfoWindow.prototype.getDbOverlaysData = function (general) { + throw new Error("Not implemented"); +}; + +/** + * Abstract method (to be implemented by subclasses) for updating content. + * + * @returns {Promise} + */ +AbstractInfoWindow.prototype.update = function () { + return this._updateContent(); +}; + +/** + * + * @param {string} params.name + * @param {AbstractDbOverlay} params.overlay + * @param {Array} params.data + * @returns {HTMLElement} + * @private + */ +AbstractInfoWindow.prototype._createTargetInfoDiv = function (params) { + var overlay = params.overlay; + var data = params.data; + var name = params.name; + + var self = this; + var result = document.createElement("div"); + + var titleElement = document.createElement("h3"); + titleElement.innerHTML = name; + result.appendChild(titleElement); + if (overlay.allowGeneralSearch()) { + var checkboxDiv = document.createElement("div"); + checkboxDiv.style.float = "right"; + + var checkbox = document.createElement("input"); + checkbox.id = "checkbox-" + name + "-" + this.getElementType() + "-" + this.getElementId(); + checkbox.type = "checkbox"; + checkbox.checked = self.isOverlayFullView(overlay.getName()); + checkbox.onclick = function () { + return self.setOverlayFullView(overlay.getName(), this.checked).then(null, GuiConnector.alert); + }; + + checkboxDiv.appendChild(checkbox); + + var description = document.createElement("div"); + description.style.float = "right"; + description.innerHTML = "Show all"; + checkboxDiv.appendChild(description); + result.appendChild(checkboxDiv); + } + var count = 0; + for (var dataId in data) { + if (data.hasOwnProperty(dataId)) { + count++; + } + } + + var table = self._createTableForTargetDiv(data, overlay); + + if (count === 0 && !overlay.allowGeneralSearch() && !this.isOverlayFullView(overlay.getName())) { + result = null; + } + if (result !== null) { + result.appendChild(table); + } + return result; +}; + +/** + * + * @param {Array} data + * @param {AbstractDbOverlay} overlay + * @returns {HTMLElement} + * @private + */ +AbstractInfoWindow.prototype._createTableForTargetDiv = function (data, overlay) { + var self = this; + var table = document.createElement("table"); + table.className = "minerva-window-drug-table"; + var header = document.createElement("tr"); + var headerCol = document.createElement("th"); + headerCol.innerHTML = "Name"; + header.appendChild(headerCol); + headerCol = document.createElement("th"); + headerCol.innerHTML = "References"; + header.appendChild(headerCol); + + var cell; + table.appendChild(header); + var row; + + var onclick = function () { + // ';' enforces single query (in case there are ',' characters in the name) + return overlay.searchByQuery(this.innerHTML + ";"); + }; + + var count = 0; + for (var searchId in data) { + if (data.hasOwnProperty(searchId)) { + + row = document.createElement("tr"); + var nameContent = searchId; + var annotations = []; + if (typeof data[searchId] === "string") { + nameContent = data[searchId]; + } else if (data[searchId] instanceof TargettingStructure) { + nameContent = data[searchId].getName(); + var targets = data[searchId].getTargetsForIdentifiedElement(self.getIdentifiedElement()); + for (var i = 0; i < targets.length; i++) { + var references = targets[i].getReferences(); + for (var j = 0; j < references.length; j++) { + annotations.push(references[j]); + } + } + } + var link = Functions.createElement({ + type: "a", + onclick: onclick, + href: "#", + content: nameContent + }); + + var nameTd = Functions.createElement({ + type: "td" + }); + nameTd.appendChild(link); + row.appendChild(nameTd); + + var referencesCell = Functions.createElement({ + type: "td" + }); + referencesCell.appendChild(self.getGuiUtils().createAnnotationList(annotations, {groupAnnotations: false})); + + row.appendChild(referencesCell); + + table.appendChild(row); + count++; + } + } + + if (self.isOverlayFullView(overlay.getName()) && count === 0) { + row = document.createElement("tr"); + cell = document.createElement("td"); + cell.colSpan = 2; + cell.innerHTML = "No results available"; + row.appendChild(cell); + table.appendChild(row); + } + + if (!self.isOverlayFullView(overlay.getName()) && count === 0 && overlay.allowGeneralSearch()) { + row = document.createElement("tr"); + cell = document.createElement("td"); + cell.colSpan = 2; + cell.innerHTML = "Search for available targets"; + row.appendChild(cell); + table.appendChild(row); + } + return table; +}; + +/** + * + * @returns {PromiseLike<any> | Promise<any>} + */ +AbstractInfoWindow.prototype.init = function () { + var self = this; + var promises = [ + // default settings of visualizing full information about elements + this.setOverlayFullView("drug", false), + this.setOverlayFullView("chemical", false), + this.setOverlayFullView("mirna", false), + this.setOverlayFullView("search", false), + // only all comments should be visible from the beginning + this.setOverlayFullView("comment", true) + ]; + + return Promise.all(promises).then(function () { + // listener called when user want to see all data about specific data overlay + var onOverlayFullViewChanged = function (e) { + var self = e.object; + // first change the content of the element + return self.update().then(function () { + if (e.newVal) { + var element = new IdentifiedElement({ + objectId: self.getElementId(), + modelId: self.getCustomMap().getId(), + type: self.getElementType() + }); + var topMap = self.getCustomMap().getTopMap(); + return topMap.retrieveOverlayDetailDataForElement(element, self.getOverlayFullViewArray()); + } + }); + + }; + + self.addPropertyChangeListener("overlayFullView", onOverlayFullViewChanged); + + self._infoWindow = self.getCustomMap().getMapCanvas().createInfoWindow({ + content: self.content, + position: self.getPosition(), + marker: self._marker + }); + + return ServerConnector.getConfiguration(); + }).then(function (configuration) { + self.getGuiUtils().setConfiguration(configuration); + self.getGuiUtils().setMap(self.getCustomMap()); + }); +}; + +/** + * + * @param {GuiUtils} guiUtils + */ +AbstractInfoWindow.prototype.setGuiUtils = function (guiUtils) { + this._guiUtils = guiUtils; +}; + +/** + * + * @returns {GuiUtils} + */ +AbstractInfoWindow.prototype.getGuiUtils = function () { + return this._guiUtils; +}; + +/** + * Creates and returns DOM div for chemical overlay information. + * + * @param {AbstractDbOverlay} overlay + * @param {Chemical[]} data + * data taken from chemical overlay + * @returns {HTMLElement} element with a div for comment overlay information + * @private + */ +AbstractInfoWindow.prototype._createChemicalInfoDiv = function (overlay, data) { + return this._createTargetInfoDiv({ + overlay: overlay, + data: data, + name: "Interacting chemicals" + }); +}; + +/** + * Creates and returns DOM div for mi rna overlay information. + * + * @param {AbstractDbOverlay} overlay + * @param {MiRna[]} data + * data taken from mi rna overlay + * @returns {HTMLElement} DOM element with a div for comment overlay information + */ +AbstractInfoWindow.prototype._createMiRnaInfoDiv = function (overlay, data) { + return this._createTargetInfoDiv({ + overlay: overlay, + data: data, + name: "Interacting Micro RNAs" + }); +}; + +/** + * + * @param {IdentifiedElement} identifiedElement + */ +AbstractInfoWindow.prototype.setIdentifiedElement = function (identifiedElement) { + if (identifiedElement === undefined) { + throw new Error("identifiedElement cannot be undefined"); + } + this._identifiedElement = identifiedElement; +}; + +/** + * + * @returns {IdentifiedElement} + */ +AbstractInfoWindow.prototype.getIdentifiedElement = function () { + return this._identifiedElement; +}; + + +/** + * Method returning identifier of the object for which this window was created. + * + * @returns {string|number} + */ +AbstractInfoWindow.prototype.getElementId = function () { + return this.getIdentifiedElement().getId(); +}; + +/** + * Method returning type of the object for which this window was created. + * + * @returns {string} + */ +AbstractInfoWindow.prototype.getElementType = function () { + return this.getIdentifiedElement().getType(); +}; + +/** + * @returns {Point} + */ +AbstractInfoWindow.prototype.getPosition = function () { + throw new Error("Not Implemented"); +}; + +module.exports = AbstractInfoWindow; diff --git a/frontend-js/src/main/js/map/window/AliasInfoWindow.js b/frontend-js/src/main/js/map/window/AliasInfoWindow.js index 0bc086e396a5753b2a0561401985f55f0ee1ec01..f80f8bfc7eeb1635491e921e36b5f9c8329ae146 100644 --- a/frontend-js/src/main/js/map/window/AliasInfoWindow.js +++ b/frontend-js/src/main/js/map/window/AliasInfoWindow.js @@ -36,10 +36,7 @@ function AliasInfoWindow(params) { this.setAlias(params.alias); var overlayListChanged = function () { - return self.getCustomMap().getAliasVisibleLayoutsData(self.getAlias().getId()).then(function (layoutAliases) { - self.layoutAliases = layoutAliases; - return self.update(); - }); + return self.update(); }; var dbOverlaySearchChanged = function () { @@ -97,99 +94,147 @@ AliasInfoWindow.prototype.init = function () { * Creates and returns chart representing data related to alias on different * overlays. * + * @param {DataOverlay[]} params.overlays + * * @returns {PromiseLike<HTMLElement>} html element representing chart with data related to alias * on different overlays */ -AliasInfoWindow.prototype.createChartDiv = function () { +AliasInfoWindow.prototype.createChartDiv = function (params) { + var overlays = params.overlays; + var result = document.createElement("div"); - var rows = []; + var promises = []; var self = this; - return Promise.each(self.layoutAliases, function (data, i) { - var rowDiv = document.createElement("div"); - if (i % 2 === 0) { - rowDiv.className = "mapChartRowEvenDiv"; - } else { - rowDiv.className = "mapChartRowOddDiv"; - } - rowDiv.style.position = "relative"; - var nameDiv = document.createElement("div"); - nameDiv.className = "mapChartNameDiv"; - nameDiv.innerHTML = self.layoutNames[i] + " "; - rowDiv.appendChild(nameDiv); - - rows[i] = rowDiv; - if (data !== undefined && data !== null) { - return Functions.overlayToColor(data).then(function (color) { - var value = parseFloat(data.value); - var description = data.description; - if (description === null || description === undefined || description === "") { - description = ""; - if (!isNaN(value)) { - description = value.toFixed(2); + + overlays.forEach(function (overlay, i) { + promises.push(overlay.getFullAliasById(self.getAlias().getId()).then(function (data) { + var rowDiv = document.createElement("div"); + if (i % 2 === 0 || self.getAlias().getLinkedSubmodelId() !== undefined) { + rowDiv.className = "minerva-chart-row-even"; + } else { + rowDiv.className = "minerva-chart-row-odd"; + } + var nameDiv = document.createElement("div"); + nameDiv.className = "minerva-chart-name"; + nameDiv.innerHTML = overlays[i].getName() + " "; + rowDiv.appendChild(nameDiv); + + if (data !== undefined && data !== null) { + return Functions.overlayToColor(data).then(function (color) { + var value = parseFloat(data.value); + var description = data.description; + if (description === null || description === undefined || description === "") { + description = ""; + if (!isNaN(value)) { + description = value.toFixed(2); + } } - } - var leftMarginDiv = document.createElement("div"); - leftMarginDiv.innerHTML = " "; - leftMarginDiv.style.float = "left"; - var centerBarDiv = document.createElement("div"); - centerBarDiv.style.width = "1px"; - centerBarDiv.style.float = "left"; - centerBarDiv.style.background = "#000000"; - centerBarDiv.innerHTML = " "; - - var rightBarDiv = document.createElement("div"); - rightBarDiv.innerHTML = " "; - rightBarDiv.style.float = "left"; - rightBarDiv.style.background = color; - rightBarDiv.style.width = Math.abs(value * 100) + "px"; - var offset = 100; - var descDiv = document.createElement("div"); - descDiv.style.float = "right"; - descDiv.style.textAlign = "right"; - descDiv.style.position = "absolute"; - descDiv.style.right = "0"; - descDiv.innerHTML = "<span>" + description + "</span>"; - if (!isNaN(value)) { - if (value > 0) { - offset = 100; - leftMarginDiv.style.width = offset + "px"; + var leftMarginDiv = document.createElement("div"); + leftMarginDiv.innerHTML = " "; + leftMarginDiv.style.float = "left"; + var centerBarDiv = document.createElement("div"); + centerBarDiv.style.width = "1px"; + centerBarDiv.style.float = "left"; + centerBarDiv.style.background = "#000000"; + centerBarDiv.innerHTML = " "; + + var rightBarDiv = document.createElement("div"); + rightBarDiv.innerHTML = " "; + rightBarDiv.style.float = "left"; + rightBarDiv.style.background = color; + rightBarDiv.style.width = Math.abs(value * 100) + "px"; + var offset = 100; + var descDiv = document.createElement("div"); + descDiv.style.float = "right"; + descDiv.style.textAlign = "right"; + descDiv.style.position = "absolute"; + descDiv.style.right = "0"; + descDiv.innerHTML = "<span>" + description + "</span>"; + if (!isNaN(value)) { + if (value > 0) { + offset = 100; + leftMarginDiv.style.width = offset + "px"; - rightBarDiv.style.textAlign = "right"; + rightBarDiv.style.textAlign = "right"; + + rowDiv.appendChild(leftMarginDiv); + rowDiv.appendChild(centerBarDiv); + rowDiv.appendChild(rightBarDiv); + } else { + offset = 100 + (value * 100); + leftMarginDiv.style.width = offset + "px"; + + rowDiv.appendChild(leftMarginDiv); + rowDiv.appendChild(rightBarDiv); + rowDiv.appendChild(centerBarDiv); + } - rowDiv.appendChild(leftMarginDiv); - rowDiv.appendChild(centerBarDiv); - rowDiv.appendChild(rightBarDiv); } else { - offset = 100 + (value * 100); + offset = 100; leftMarginDiv.style.width = offset + "px"; - + leftMarginDiv.style.background = color; + rightBarDiv.style.width = offset + "px"; + rightBarDiv.style.background = color; + rightBarDiv.style.textAlign = "right"; rowDiv.appendChild(leftMarginDiv); - rowDiv.appendChild(rightBarDiv); rowDiv.appendChild(centerBarDiv); + rowDiv.appendChild(rightBarDiv); + } + rowDiv.appendChild(descDiv); + return rowDiv; + }); + } else { + var emptyDiv = document.createElement("div"); + emptyDiv.innerHTML = " "; + emptyDiv.style.float = "left"; + emptyDiv.style.width = "201px"; + rowDiv.appendChild(emptyDiv); + return rowDiv; + } + })); + if (self.getAlias().getLinkedSubmodelId() !== undefined) { + promises.push(new Promise.resolve(overlay).then(function (overlay) { + var overlayData = overlay.getAliases(); + var overlayDataOnSubmap = []; + for (var j = 0; j < overlayData.length; j++) { + var data = overlayData[j]; + if (data.getModelId() === self.getAlias().getLinkedSubmodelId()) { + overlayDataOnSubmap.push(data); } - - } else { - offset = 100; - leftMarginDiv.style.width = offset + "px"; - leftMarginDiv.style.background = color; - rightBarDiv.style.width = offset + "px"; - rightBarDiv.style.background = color; - rightBarDiv.style.textAlign = "right"; - rowDiv.appendChild(leftMarginDiv); - rowDiv.appendChild(centerBarDiv); - rowDiv.appendChild(rightBarDiv); } - rowDiv.appendChild(descDiv); - }); - } else { - var emptyDiv = document.createElement("div"); - emptyDiv.innerHTML = " "; - emptyDiv.style.float = "left"; - emptyDiv.style.width = "201px"; - rowDiv.appendChild(emptyDiv); - return Promise.resolve(); + return Functions.overlaysToColorDataStructure(overlayDataOnSubmap).then(function (colors) { + var rowDiv = document.createElement("div"); + rowDiv.className = "minerva-chart-row-odd"; + var nameDiv = document.createElement("div"); + nameDiv.className = "minerva-chart-name"; + var submapName = self.getCustomMap().getTopMap().getSubmapById(self.getAlias().getLinkedSubmodelId()).getModel().getName(); + nameDiv.innerHTML = "Submap " + submapName; + rowDiv.appendChild(nameDiv); + + var emptyDiv = document.createElement("div"); + emptyDiv.style.float = "left"; + emptyDiv.style.width = "201px"; + rowDiv.appendChild(emptyDiv); + + var totalAmount = 0; + for (var j = 0; j < colors.length; j++) { + totalAmount += colors[j].amount; + } + + for (j = 0; j < colors.length; j++) { + var overlayDataDiv = document.createElement("div"); + overlayDataDiv.innerHTML = " "; + overlayDataDiv.style.float = "left"; + overlayDataDiv.style.width = Math.floor(100*colors[j].amount / totalAmount) + "%"; + overlayDataDiv.style.background = colors[j].color; + emptyDiv.appendChild(overlayDataDiv); + } + return rowDiv; + }); + })); } - }).then(function () { + }); + return Promise.all(promises).then(function (rows) { for (var i = 0; i < rows.length; i++) { result.appendChild(rows[i]); } @@ -215,18 +260,14 @@ AliasInfoWindow.prototype.createContentDiv = function () { result.appendChild(overlayDiv); - return self.getCustomMap().getAliasVisibleLayoutsData(alias.getId()).then(function (layoutAliases) { - self.layoutAliases = layoutAliases; - return self.getCustomMap().getTopMap().getVisibleDataOverlays(); - }).then(function (dataOverlays) { - self.layoutNames = []; - for (var i = 0; i < dataOverlays.length; i++) { - self.layoutNames.push(dataOverlays[i].getName()); - } - return self.createChartDiv(); + var overlays; + + return self.getCustomMap().getTopMap().getVisibleDataOverlays().then(function (dataOverlays) { + overlays = dataOverlays; + return self.createChartDiv({overlays: overlays}); }).then(function (chartDiv) { overlayDiv.appendChild(chartDiv); - return self.createGenomicDiv(); + return self.createGenomicDiv({overlays: overlays}); }).then(function (genomicDiv) { overlayDiv.appendChild(genomicDiv); return result; @@ -245,15 +286,19 @@ AliasInfoWindow.prototype.createContentDiv = function () { * * @returns {Promise} array with data from {@link AbstractDbOverlay} */ -AliasInfoWindow.prototype.getOverlaysData = function (general) { +AliasInfoWindow.prototype.getDbOverlaysData = function (general) { return this.getCustomMap().getTopMap().getOverlayDataForAlias(this.getAlias(), general); }; /** * - * @returns {PromiseLike<HTMLElement>} + * @param {DataOverlay[]} params.overlays + * + * @returns {Promise|PromiseLike} */ -AliasInfoWindow.prototype.createGenomicDiv = function () { +AliasInfoWindow.prototype.createGenomicDiv = function (params) { + var overlays = params.overlays; + var self = this; var result = document.createElement("div"); @@ -285,34 +330,41 @@ AliasInfoWindow.prototype.createGenomicDiv = function () { var globalGeneVariants = []; - return Promise.each( - self.layoutAliases, - function (data) { + var promises = []; + var overlaysData = []; + + overlays.forEach(function (overlay) { + promises.push(overlay.getFullAliasById(self.getAlias().getId())); + }); + return Promise.all(promises).then(function (result) { + promises = []; + overlaysData = result; + for (var i = 0; i < overlaysData.length; i++) { + var data = overlaysData[i]; if (data !== null && data !== undefined && data.getType() === LayoutAlias.GENETIC_VARIANT) { geneticInformation = true; - return Promise.each(data.getGeneVariants(), function (variant) { + promises.push(Promise.each(data.getGeneVariants(), function (variant) { return self.getCustomMap().getTopMap().getReferenceGenome(variant.getReferenceGenomeType(), - variant.getReferenceGenomeVersion()).then( - function (genome) { - if (genome.getUrl() !== null && genome.getUrl() !== undefined) { - if (genomes[genome.getUrl()] === undefined) { - genomes[genome.getUrl()] = genome; - genomeUrls.push(genome.getUrl()); - } - } else { - logger.warn("Genome for " + variant.getReferenceGenomeType() + "," - + variant.getReferenceGenomeVersion() + " not loaded"); + variant.getReferenceGenomeVersion()).then(function (genome) { + if (genome.getUrl() !== null && genome.getUrl() !== undefined) { + if (genomes[genome.getUrl()] === undefined) { + genomes[genome.getUrl()] = genome; + genomeUrls.push(genome.getUrl()); } - }, - function () { + } else { logger.warn("Genome for " + variant.getReferenceGenomeType() + "," + variant.getReferenceGenomeVersion() + " not loaded"); + } + }, function () { + logger.warn("Genome for " + variant.getReferenceGenomeType() + "," + + variant.getReferenceGenomeVersion() + " not loaded"); - }); - }); - + }); + })); } - }).then(function () { + } + return Promise.all(promises); + }).then(function () { for (var i = 0; i < genomeUrls.length; i++) { var genome = genomes[genomeUrls[i]]; pileupSource.splice(0, 0, { @@ -334,7 +386,8 @@ AliasInfoWindow.prototype.createGenomicDiv = function () { }); } } - return Promise.each(self.layoutAliases, function (data, i) { + for (i = 0; i < overlaysData.length; i++) { + var data = overlaysData[i]; globalGeneVariants[i] = []; if (data !== null && data !== undefined && data.getType() === LayoutAlias.GENETIC_VARIANT) { var geneVariants = data.getGeneVariants(); @@ -349,13 +402,12 @@ AliasInfoWindow.prototype.createGenomicDiv = function () { pileupRange.stop = Math.max(pileupRange.stop, variant.getPosition() + length); } } - }); - }).then(function () { + } if (geneticInformation) { if (genomeUrls.length === 0) { contentElement.innerHTML = "No reference genome data available on minerva platform"; } else { - for (var i = 0; i < self.layoutAliases.length; i++) { + for (i = 0; i < overlaysData.length; i++) { if (globalGeneVariants[i].length > 0) { var vcfContent = self.createVcfString(globalGeneVariants[i]); pileupSource.push({ @@ -363,7 +415,7 @@ AliasInfoWindow.prototype.createGenomicDiv = function () { data: pileup.formats.vcf({ content: vcfContent }), - name: self.layoutNames[i] + ' - Variants', + name: overlays[i].getName() + ' - Variants', options: { variantHeightByFrequency: true } @@ -493,5 +545,4 @@ AliasInfoWindow.prototype.getPosition = function () { return new Point(alias.x + alias.width / 2, alias.y + alias.height / 2); }; - module.exports = AliasInfoWindow; diff --git a/frontend-js/src/main/js/map/window/PointInfoWindow.js b/frontend-js/src/main/js/map/window/PointInfoWindow.js index dc1c2d7f8bb90b04f783ce2ebd63acbad6f380ba..bf263c8e7a751e2e94ac1497e077cc2614c78f02 100644 --- a/frontend-js/src/main/js/map/window/PointInfoWindow.js +++ b/frontend-js/src/main/js/map/window/PointInfoWindow.js @@ -1,63 +1,63 @@ -"use strict"; - -var Promise = require("bluebird"); - -var AbstractInfoWindow = require('./AbstractInfoWindow'); -var IdentifiedElement = require('../data/IdentifiedElement'); - -/** - * - * @param {IdentifiedElement} [params.identifiedElement] - * @param {AbstractCustomMap} params.map - * @param {Marker} params.marker - * @param {PointData} params.point - * - * @constructor - * @extends AbstractInfoWindow - */ -function PointInfoWindow(params) { - if (params.identifiedElement === undefined) { - params.identifiedElement = new IdentifiedElement(params.point); - } - // call super constructor - AbstractInfoWindow.call(this, params); - - this.pointData = params.point; - -} - -PointInfoWindow.prototype = Object.create(AbstractInfoWindow.prototype); -PointInfoWindow.prototype.constructor = PointInfoWindow; - -/** - * - * @returns {PromiseLike<HTMLElement>} - */ -PointInfoWindow.prototype.createContentDiv = function () { - var result = document.createElement("div"); - var title = document.createElement("h3"); - title.innerHTML = "Point: " + this.pointData.getPoint(); - result.appendChild(title); - - return Promise.resolve(result); -}; - -/** - * - * @param {Object.<string,boolean>} general - * @returns {Promise} - */ -PointInfoWindow.prototype.getOverlaysData = function (general) { - return this.getCustomMap().getTopMap().getOverlayDataForPoint(this.pointData, general); -}; - -/** - * - * @returns {Point} - */ -PointInfoWindow.prototype.getPosition = function () { - return this.pointData.getPoint(); -}; - - -module.exports = PointInfoWindow; +"use strict"; + +var Promise = require("bluebird"); + +var AbstractInfoWindow = require('./AbstractInfoWindow'); +var IdentifiedElement = require('../data/IdentifiedElement'); + +/** + * + * @param {IdentifiedElement} [params.identifiedElement] + * @param {AbstractCustomMap} params.map + * @param {Marker} params.marker + * @param {PointData} params.point + * + * @constructor + * @extends AbstractInfoWindow + */ +function PointInfoWindow(params) { + if (params.identifiedElement === undefined) { + params.identifiedElement = new IdentifiedElement(params.point); + } + // call super constructor + AbstractInfoWindow.call(this, params); + + this.pointData = params.point; + +} + +PointInfoWindow.prototype = Object.create(AbstractInfoWindow.prototype); +PointInfoWindow.prototype.constructor = PointInfoWindow; + +/** + * + * @returns {PromiseLike<HTMLElement>} + */ +PointInfoWindow.prototype.createContentDiv = function () { + var result = document.createElement("div"); + var title = document.createElement("h3"); + title.innerHTML = "Point: " + this.pointData.getPoint(); + result.appendChild(title); + + return Promise.resolve(result); +}; + +/** + * + * @param {Object.<string,boolean>} general + * @returns {Promise} + */ +PointInfoWindow.prototype.getDbOverlaysData = function (general) { + return this.getCustomMap().getTopMap().getOverlayDataForPoint(this.pointData, general); +}; + +/** + * + * @returns {Point} + */ +PointInfoWindow.prototype.getPosition = function () { + return this.pointData.getPoint(); +}; + + +module.exports = PointInfoWindow; diff --git a/frontend-js/src/main/js/map/window/ReactionInfoWindow.js b/frontend-js/src/main/js/map/window/ReactionInfoWindow.js index cca0f9d2c820e3e6b6ebe8ed31a42415f8ffc07d..bd6b7c493c9be2b3b0d3539a3829c76b95bd7db0 100644 --- a/frontend-js/src/main/js/map/window/ReactionInfoWindow.js +++ b/frontend-js/src/main/js/map/window/ReactionInfoWindow.js @@ -1,264 +1,264 @@ -"use strict"; - -var Promise = require("bluebird"); - -var AbstractInfoWindow = require('./AbstractInfoWindow'); -var GuiUtils = require('../../gui/leftPanel/GuiUtils'); -var IdentifiedElement = require('../data/IdentifiedElement'); -var Reaction = require('../data/Reaction'); -var Functions = require('../../Functions'); -var logger = require('../../logger'); - -/** - * Class representing info window that should be opened when clicking on - * reaction. - */ -/** - * - * @param {IdentifiedElement} [params.identifiedElement] - * @param {AbstractCustomMap} params.map - * @param {Marker} params.marker - * @param {Reaction} params.reaction - * - * @constructor - * @extends AbstractInfoWindow - */ -function ReactionInfoWindow(params) { - if (params.identifiedElement === undefined) { - params.identifiedElement = new IdentifiedElement(params.reaction); - } - // call super constructor - AbstractInfoWindow.call(this, params); - - var self = this; - - self.setReactionData(params.reaction); - if (params.reaction.getKineticLaw() !== undefined) { - self.addListener("onShow", function () { - return MathJax.Hub.Queue(["Typeset", MathJax.Hub]); - }); - } -} - -ReactionInfoWindow.prototype = Object.create(AbstractInfoWindow.prototype); -ReactionInfoWindow.prototype.constructor = ReactionInfoWindow; - -/** - * Methods that creates and return html code with the content of the window. - * - * @returns {Promise} representing html code for content of the info window - */ -ReactionInfoWindow.prototype.createContentDiv = function () { - var self = this; - var reaction = self.getReactionData(); - var result = document.createElement("div"); - var title = document.createElement("h3"); - title.innerHTML = "Reaction: " + reaction.getReactionId(); - result.appendChild(title); - - return self.createKineticsDiv(reaction, result).then(function () { - result.appendChild(self.createElementsDiv(reaction)); - return result; - }); -}; - -/** - * - * @param {Reaction} reaction - * @param {HTMLElement} result - * @returns {Promise} - */ -ReactionInfoWindow.prototype.createKineticsDiv = function (reaction, result) { - var self = this; - if (reaction.getKineticLaw() === undefined) { - return Promise.resolve(); - } else { - var kineticLaw = reaction.getKineticLaw(); - return Functions.loadScript('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML').then(function () { - return MathJax.Hub.Config({ - tex2jax: { - skipTags: ["script", "noscript", "style", "textarea", "pre", "code"] - } - }); - }).then(function () { - - result.appendChild(Functions.createElement({type: "h4", content: "Kinetic law"})); - - if (kineticLaw.getMathMlPresentation() !== undefined) { - result.appendChild(Functions.createElement({ - type: "div", - content: kineticLaw.getMathMlPresentation(), - xss: false - })); - } else { - - result.appendChild(Functions.createElement({ - type: "div", - content: "<p>Problematic MathML</p>" - })); - logger.warn("Problematic MathML: " + kineticLaw.getDefinition()); - } - var promises = []; - for (var i = 0; i < kineticLaw.getFunctionIds().length; i++) { - promises.push(self.getCustomMap().getModel().getSbmlFunctionById(kineticLaw.getFunctionIds()[i])); - } - return Promise.all(promises); - }).then(function (functions) { - result.appendChild(self.createSbmlFunctionDiv(functions)); - - var promises = []; - for (var i = 0; i < kineticLaw.getParameterIds().length; i++) { - promises.push(self.getCustomMap().getModel().getSbmlParameterById(kineticLaw.getParameterIds()[i])); - } - return Promise.all(promises); - }).then(function (parameters) { - result.appendChild(self.createSbmlParameterDiv(parameters)); - }); - } -}; - -/** - * - * @param {SbmlFunction[]} functions - * @returns {HTMLElement} - */ -ReactionInfoWindow.prototype.createSbmlFunctionDiv = function (functions) { - var result = Functions.createElement({type: "div"}); - if (functions.length > 0) { - result.appendChild(Functions.createElement({type: "h5", content: "Functions: "})); - var guiUtils = new GuiUtils(); - var table = Functions.createElement({type: "div", style: "display: table;", className: "borderTable"}); - table.appendChild(guiUtils.createTableRow(["Name", "Definition", "Arguments"])); - for (var i = 0; i < functions.length; i++) { - var sbmlFunction = functions[i]; - var mathML; - if (sbmlFunction.getMathMlPresentation() !== undefined) { - mathML = sbmlFunction.getMathMlPresentation(); - } else { - mathML = "<p>Problematic MathML</p>"; - logger.warn("Problematic MathML: " + sbmlFunction.getDefinition()); - } - var functionArguments = sbmlFunction.getArguments().join(", "); - table.appendChild(guiUtils.createTableRow([sbmlFunction.getName(), mathML, functionArguments])); - } - result.appendChild(table); - } - return result; -}; - -/** - * - * @param {SbmlParameter[]} parameters - * @returns {HTMLElement} - */ -ReactionInfoWindow.prototype.createSbmlParameterDiv = function (parameters) { - var result = Functions.createElement({type: "div"}); - if (parameters.length > 0) { - result.appendChild(Functions.createElement({type: "h5", content: "Parameters: "})); - var guiUtils = new GuiUtils(); - var table = Functions.createElement({type: "div", style: "display: table;", className: "borderTable"}); - table.appendChild(guiUtils.createTableRow(["Name", "parameterId", "Value", "Global"])); - for (var i = 0; i < parameters.length; i++) { - var sbmlFunction = parameters[i]; - table.appendChild(guiUtils.createTableRow([sbmlFunction.getName(), sbmlFunction.getParameterId(), sbmlFunction.getValue(), sbmlFunction.getGlobal()])); - } - result.appendChild(table); - } - return result; -}; - -/** - * - * @param {Reaction} reaction - * @returns {HTMLElement} - */ -ReactionInfoWindow.prototype.createElementsDiv = function (reaction) { - var result = Functions.createElement({type: "div"}); - result.appendChild(Functions.createElement({type: "h5", content: "Elements: "})); - var guiUtils = new GuiUtils(); - var table = Functions.createElement({type: "div", style: "display: table;", className: "borderTable"}); - table.appendChild(guiUtils.createTableRow(["Name", "Role", "elementId", "Constant", "Boundary condition", "Initial concentration", "Initial amount", "Stoichiometry"])); - var elements = reaction.getReactants(); - var i, element; - - function createRow(node, title) { - var element = node.getAlias(); - var stoichiometry = node.getStoichiometry(); - if (stoichiometry === undefined) { - stoichiometry = ""; - } - return guiUtils.createTableRow([element.getName(), title, element.getElementId(), element.getConstant(), element.getBoundaryCondition(), element.getInitialConcentration(), element.getInitialAmount(), stoichiometry]) - } - - for (i = 0; i < elements.length; i++) { - element = elements[i].getAlias(); - table.appendChild(createRow(elements[i], "Reactant")); - } - elements = reaction.getProducts(); - for (i = 0; i < elements.length; i++) { - element = elements[i].getAlias(); - table.appendChild(createRow(elements[i], "Product")); - } - elements = reaction.getModifiers(); - for (i = 0; i < elements.length; i++) { - element = elements[i].getAlias(); - table.appendChild(createRow(elements[i], "Modifier")); - } - result.appendChild(table); - return result; -}; - -/** - * - * @returns {PromiseLike<any> | Promise<any>} - */ -ReactionInfoWindow.prototype.init = function () { - var self = this; - return Promise.resolve().then(function () { - return AbstractInfoWindow.prototype.init.call(self); - }).then(function () { - return self.update(); - }); -}; - -/** - * Returns array with data taken from all known {@link AbstractDbOverlay}. - * - * @param {Object.<string,boolean>} general - * @returns {Promise} of an array with data from {@link AbstractDbOverlay} - */ -ReactionInfoWindow.prototype.getOverlaysData = function (general) { - return this.getCustomMap().getTopMap().getOverlayDataForReaction(this.getReactionData(), general); -}; - -/** - * - * @returns {Reaction} - */ -ReactionInfoWindow.prototype.getReactionData = function () { - return this._reactionData; -}; - -/** - * - * @param {Reaction} reactionData - */ -ReactionInfoWindow.prototype.setReactionData = function (reactionData) { - if (reactionData === undefined || reactionData === null) { - throw new Error("Reaction must be specified"); - } else if (reactionData instanceof Reaction) { - this._reactionData = reactionData; - } else { - throw new Error("Parameter must be of Reaction type, but found" + reactionData); - } -}; - -/** - * - * @returns {Point} - */ -ReactionInfoWindow.prototype.getPosition = function () { - return this.getReactionData().getCenter(); -}; - -module.exports = ReactionInfoWindow; +"use strict"; + +var Promise = require("bluebird"); + +var AbstractInfoWindow = require('./AbstractInfoWindow'); +var GuiUtils = require('../../gui/leftPanel/GuiUtils'); +var IdentifiedElement = require('../data/IdentifiedElement'); +var Reaction = require('../data/Reaction'); +var Functions = require('../../Functions'); +var logger = require('../../logger'); + +/** + * Class representing info window that should be opened when clicking on + * reaction. + */ +/** + * + * @param {IdentifiedElement} [params.identifiedElement] + * @param {AbstractCustomMap} params.map + * @param {Marker} params.marker + * @param {Reaction} params.reaction + * + * @constructor + * @extends AbstractInfoWindow + */ +function ReactionInfoWindow(params) { + if (params.identifiedElement === undefined) { + params.identifiedElement = new IdentifiedElement(params.reaction); + } + // call super constructor + AbstractInfoWindow.call(this, params); + + var self = this; + + self.setReactionData(params.reaction); + if (params.reaction.getKineticLaw() !== undefined) { + self.addListener("onShow", function () { + return MathJax.Hub.Queue(["Typeset", MathJax.Hub]); + }); + } +} + +ReactionInfoWindow.prototype = Object.create(AbstractInfoWindow.prototype); +ReactionInfoWindow.prototype.constructor = ReactionInfoWindow; + +/** + * Methods that creates and return html code with the content of the window. + * + * @returns {Promise} representing html code for content of the info window + */ +ReactionInfoWindow.prototype.createContentDiv = function () { + var self = this; + var reaction = self.getReactionData(); + var result = document.createElement("div"); + var title = document.createElement("h3"); + title.innerHTML = "Reaction: " + reaction.getReactionId(); + result.appendChild(title); + + return self.createKineticsDiv(reaction, result).then(function () { + result.appendChild(self.createElementsDiv(reaction)); + return result; + }); +}; + +/** + * + * @param {Reaction} reaction + * @param {HTMLElement} result + * @returns {Promise} + */ +ReactionInfoWindow.prototype.createKineticsDiv = function (reaction, result) { + var self = this; + if (reaction.getKineticLaw() === undefined) { + return Promise.resolve(); + } else { + var kineticLaw = reaction.getKineticLaw(); + return Functions.loadScript('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML').then(function () { + return MathJax.Hub.Config({ + tex2jax: { + skipTags: ["script", "noscript", "style", "textarea", "pre", "code"] + } + }); + }).then(function () { + + result.appendChild(Functions.createElement({type: "h4", content: "Kinetic law"})); + + if (kineticLaw.getMathMlPresentation() !== undefined) { + result.appendChild(Functions.createElement({ + type: "div", + content: kineticLaw.getMathMlPresentation(), + xss: false + })); + } else { + + result.appendChild(Functions.createElement({ + type: "div", + content: "<p>Problematic MathML</p>" + })); + logger.warn("Problematic MathML: " + kineticLaw.getDefinition()); + } + var promises = []; + for (var i = 0; i < kineticLaw.getFunctionIds().length; i++) { + promises.push(self.getCustomMap().getModel().getSbmlFunctionById(kineticLaw.getFunctionIds()[i])); + } + return Promise.all(promises); + }).then(function (functions) { + result.appendChild(self.createSbmlFunctionDiv(functions)); + + var promises = []; + for (var i = 0; i < kineticLaw.getParameterIds().length; i++) { + promises.push(self.getCustomMap().getModel().getSbmlParameterById(kineticLaw.getParameterIds()[i])); + } + return Promise.all(promises); + }).then(function (parameters) { + result.appendChild(self.createSbmlParameterDiv(parameters)); + }); + } +}; + +/** + * + * @param {SbmlFunction[]} functions + * @returns {HTMLElement} + */ +ReactionInfoWindow.prototype.createSbmlFunctionDiv = function (functions) { + var result = Functions.createElement({type: "div"}); + if (functions.length > 0) { + result.appendChild(Functions.createElement({type: "h5", content: "Functions: "})); + var guiUtils = new GuiUtils(); + var table = Functions.createElement({type: "div", style: "display: table;", className: "borderTable"}); + table.appendChild(guiUtils.createTableRow(["Name", "Definition", "Arguments"])); + for (var i = 0; i < functions.length; i++) { + var sbmlFunction = functions[i]; + var mathML; + if (sbmlFunction.getMathMlPresentation() !== undefined) { + mathML = sbmlFunction.getMathMlPresentation(); + } else { + mathML = "<p>Problematic MathML</p>"; + logger.warn("Problematic MathML: " + sbmlFunction.getDefinition()); + } + var functionArguments = sbmlFunction.getArguments().join(", "); + table.appendChild(guiUtils.createTableRow([sbmlFunction.getName(), mathML, functionArguments])); + } + result.appendChild(table); + } + return result; +}; + +/** + * + * @param {SbmlParameter[]} parameters + * @returns {HTMLElement} + */ +ReactionInfoWindow.prototype.createSbmlParameterDiv = function (parameters) { + var result = Functions.createElement({type: "div"}); + if (parameters.length > 0) { + result.appendChild(Functions.createElement({type: "h5", content: "Parameters: "})); + var guiUtils = new GuiUtils(); + var table = Functions.createElement({type: "div", style: "display: table;", className: "borderTable"}); + table.appendChild(guiUtils.createTableRow(["Name", "parameterId", "Value", "Global"])); + for (var i = 0; i < parameters.length; i++) { + var sbmlFunction = parameters[i]; + table.appendChild(guiUtils.createTableRow([sbmlFunction.getName(), sbmlFunction.getParameterId(), sbmlFunction.getValue(), sbmlFunction.getGlobal()])); + } + result.appendChild(table); + } + return result; +}; + +/** + * + * @param {Reaction} reaction + * @returns {HTMLElement} + */ +ReactionInfoWindow.prototype.createElementsDiv = function (reaction) { + var result = Functions.createElement({type: "div"}); + result.appendChild(Functions.createElement({type: "h5", content: "Elements: "})); + var guiUtils = new GuiUtils(); + var table = Functions.createElement({type: "div", style: "display: table;", className: "borderTable"}); + table.appendChild(guiUtils.createTableRow(["Name", "Role", "elementId", "Constant", "Boundary condition", "Initial concentration", "Initial amount", "Stoichiometry"])); + var elements = reaction.getReactants(); + var i, element; + + function createRow(node, title) { + var element = node.getAlias(); + var stoichiometry = node.getStoichiometry(); + if (stoichiometry === undefined) { + stoichiometry = ""; + } + return guiUtils.createTableRow([element.getName(), title, element.getElementId(), element.getConstant(), element.getBoundaryCondition(), element.getInitialConcentration(), element.getInitialAmount(), stoichiometry]) + } + + for (i = 0; i < elements.length; i++) { + element = elements[i].getAlias(); + table.appendChild(createRow(elements[i], "Reactant")); + } + elements = reaction.getProducts(); + for (i = 0; i < elements.length; i++) { + element = elements[i].getAlias(); + table.appendChild(createRow(elements[i], "Product")); + } + elements = reaction.getModifiers(); + for (i = 0; i < elements.length; i++) { + element = elements[i].getAlias(); + table.appendChild(createRow(elements[i], "Modifier")); + } + result.appendChild(table); + return result; +}; + +/** + * + * @returns {PromiseLike<any> | Promise<any>} + */ +ReactionInfoWindow.prototype.init = function () { + var self = this; + return Promise.resolve().then(function () { + return AbstractInfoWindow.prototype.init.call(self); + }).then(function () { + return self.update(); + }); +}; + +/** + * Returns array with data taken from all known {@link AbstractDbOverlay}. + * + * @param {Object.<string,boolean>} general + * @returns {Promise} of an array with data from {@link AbstractDbOverlay} + */ +ReactionInfoWindow.prototype.getDbOverlaysData = function (general) { + return this.getCustomMap().getTopMap().getOverlayDataForReaction(this.getReactionData(), general); +}; + +/** + * + * @returns {Reaction} + */ +ReactionInfoWindow.prototype.getReactionData = function () { + return this._reactionData; +}; + +/** + * + * @param {Reaction} reactionData + */ +ReactionInfoWindow.prototype.setReactionData = function (reactionData) { + if (reactionData === undefined || reactionData === null) { + throw new Error("Reaction must be specified"); + } else if (reactionData instanceof Reaction) { + this._reactionData = reactionData; + } else { + throw new Error("Parameter must be of Reaction type, but found" + reactionData); + } +}; + +/** + * + * @returns {Point} + */ +ReactionInfoWindow.prototype.getPosition = function () { + return this.getReactionData().getCenter(); +}; + +module.exports = ReactionInfoWindow; diff --git a/frontend-js/src/test/js/helper.js b/frontend-js/src/test/js/helper.js index 30002e661c6ffe0c06d0535660fc507cbfbc276a..11fc0efa1884a43783a7801b84373de106a9b633 100644 --- a/frontend-js/src/test/js/helper.js +++ b/frontend-js/src/test/js/helper.js @@ -223,9 +223,11 @@ Helper.prototype.createAlias = function (map) { /** * * @param {Alias} [alias] + * @param {string} [type] + * * @returns {LayoutAlias} */ -Helper.prototype.createLayoutAlias = function (alias) { +Helper.prototype.createLayoutAlias = function (alias, type) { var id; var modelId; if (alias instanceof Alias) { @@ -242,7 +244,8 @@ Helper.prototype.createLayoutAlias = function (alias) { a: 23 }, modelId: modelId, - geneVariations: [] + geneVariations: [], + type: type }); }; diff --git a/frontend-js/src/test/js/map/CustomMap-test.js b/frontend-js/src/test/js/map/CustomMap-test.js index 9c8cf3654a232c44fa8853d325fd2631a9d73fda..880efabfaac797fc04af47722fd81ac9caf3c0b3 100644 --- a/frontend-js/src/test/js/map/CustomMap-test.js +++ b/frontend-js/src/test/js/map/CustomMap-test.js @@ -1,1037 +1,1021 @@ -"use strict"; - -var Promise = require("bluebird"); - -require("../mocha-config.js"); - -var AliasMarker = require('../../../main/js/map/marker/AliasMarker'); -var AliasSurface = require('../../../main/js/map/surface/AliasSurface'); -var Comment = require('../../../main/js/map/data/Comment'); -var ControlType = require('../../../main/js/map/ControlType'); -var CustomMap = require('../../../main/js/map/CustomMap'); -var IdentifiedElement = require('../../../main/js/map/data/IdentifiedElement'); -var MapContextMenu = require('../../../main/js/gui/MapContextMenu'); -var MolArt = require('../../../main/js/map/structure/MolArt'); -var Point = require('../../../main/js/map/canvas/Point'); -var PointData = require('../../../main/js/map/data/PointData'); -var PointMarker = require('../../../main/js/map/marker/PointMarker'); -var ReactionMarker = require('../../../main/js/map/marker/ReactionMarker'); -var ReactionSurface = require('../../../main/js/map/surface/ReactionSurface'); - -var ServerConnector = require('./../ServerConnector-mock'); - -var logger = require('./../logger'); - -var chai = require('chai'); -var assert = chai.assert; - -describe('CustomMap', function () { - describe("constructor", function () { - it("default", function () { - var options = helper.createCustomMapOptions(); - var map = new CustomMap(options); - assert.ok(map); - }); - - it("with submaps", function () { - var options = helper.createCustomMapOptions(); - - options.getProject().addModel(helper.createModel()); - - var map = new CustomMap(options); - assert.ok(map); - }); - - it("with session data pointing to not existing overlay", function () { - var options = helper.createCustomMapOptions(); - - ServerConnector.getSessionData(options.getProject()).setSelectedBackgroundOverlay("-1"); - - var map = new CustomMap(options); - assert.ok(map); - }); - }); - - it("getSubmapById", function () { - var map = helper.createCustomMap(); - assert.ok(map.getSubmapById(map.getId())); - }); - - it("getSubmapById (invalid)", function () { - var map = helper.createCustomMap(); - assert.equal(map.getSubmapById(-1), null); - }); - - it("getSubmapById (string id)", function () { - var map = helper.createCustomMap(); - assert.ok(map.getSubmapById(map.getId() + "")); - }); - - describe("openDataOverlay", function () { - it("for not existing id", function () { - var map = helper.createCustomMap(); - try { - map.openDataOverlay(-1); - assert.ok(false); - } catch (exception) { - assert.ok(exception.message.indexOf("You have no privileges") >= 0); - } - }); - - it("for int id", function () { - var options = helper.createCustomMapOptions(); - var layout = options.getProject().getDataOverlays()[0]; - var map = new CustomMap(options); - map.openDataOverlay(layout.getId()); - assert.equal(logger.getErrors().length, 0); - }); - - it("for overlay object", function () { - var options = helper.createCustomMapOptions(); - var layout = options.getProject().getDataOverlays()[0]; - var map = new CustomMap(options); - map.openDataOverlay(layout); - assert.equal(logger.getErrors().length, 0); - }); - - it("for string id", function () { - var options = helper.createCustomMapOptions(); - var layout = options.getProject().getDataOverlays()[0]; - var map = new CustomMap(options); - map.openDataOverlay(layout.getId() + ""); - assert.equal(logger.getErrors().length, 0); - }); - - it("with background overlay", function () { - var map = helper.createCustomMap(); - var layout = helper.createOverlay(); - layout.setInitialized(true); - layout.setInputDataAvailable(false); - map.getProject().addDataOverlay(layout); - - return map.openDataOverlay(layout.getId()).then(function () { - var vLayouts = ServerConnector.getSessionData(map.getProject()).getVisibleOverlays(); - assert.equal(0, vLayouts.length); - }); - }); - - it("with non background overlay", function () { - var project = helper.createProject(); - var layout = helper.createOverlay(); - layout.setInitialized(true); - layout.setInputDataAvailable(true); - project.addDataOverlay(layout); - - var emptyBackground = helper.createOverlay(); - emptyBackground.setInputDataAvailable(false); - emptyBackground.setName("Empty"); - project.addDataOverlay(emptyBackground); - - var map = helper.createCustomMap(project); - - - return map.openDataOverlay(layout.getId()).then(function () { - var backgroundId = ServerConnector.getSessionData(project).getSelectedBackgroundOverlay(); - assert.equal(backgroundId, emptyBackground.getId()); - }); - }); - - it("check backgroundChangeListener", function () { - var project = helper.createProject(); - var overlay = helper.createOverlay(); - overlay.setInitialized(true); - overlay.setInputDataAvailable(true); - project.addDataOverlay(overlay); - - var overlay2 = helper.createOverlay(); - overlay2.setInitialized(true); - overlay2.setInputDataAvailable(true); - project.addDataOverlay(overlay2); - - var emptyBackground = helper.createOverlay(); - emptyBackground.setInputDataAvailable(false); - emptyBackground.setName("Empty"); - project.addDataOverlay(emptyBackground); - - var map = helper.createCustomMap(project); - - var counter = 0; - map.addListener("onBackgroundOverlayChange", function () { - counter++; - }); - - return map.openDataOverlay(overlay.getId()).then(function () { - assert.equal(1, counter, "listener wasn't fired"); - return map.openDataOverlay(overlay2.getId()); - }).then(function () { - assert.equal(1, counter, "listener shouldn't be fired again because nothing changed"); - }); - }); - - it("simple", function () { - var map = helper.createCustomMap(); - var alias = helper.createAlias(map); - map.getModel().addAlias(alias); - - var reaction = helper.createReaction(map); - map.getModel().addReaction(reaction); - - var layout = helper.createOverlay(); - layout.setInputDataAvailable(true); - layout.setInitialized(true); - var layoutAlias = helper.createLayoutAlias(alias); - layout.addAlias(layoutAlias); - - var layoutReaction = helper.createLayoutReaction(reaction); - layout.addReaction(layoutReaction); - - map.getProject().addDataOverlay(layout); - - return map.openDataOverlay(layout.getId()).then(function () { - return map._showSelectedDataOverlay(layout.getId(), 0, 1); - }).then(function () { - var vLayouts = ServerConnector.getSessionData(map.getProject()).getVisibleOverlays(); - assert.equal(1, vLayouts.length); - assert.equal(layout.getId(), vLayouts[0]); - - assert.equal(2, map.selectedLayoutOverlays[layout.getId()].length); - assert.ok(map.selectedLayoutOverlays[layout.getId()][0] instanceof AliasSurface); - assert.ok(map.selectedLayoutOverlays[layout.getId()][1] instanceof ReactionSurface); - - // now hide the layout - return map._hideSelectedLayout(layout.getId()); - }).then(function () { - assert.ok(map.selectedLayoutOverlays[layout.getId()]); - assert.equal(0, map.selectedLayoutOverlays[layout.getId()].length); - }); - - }); - - it("with submaps", function () { - var projectId = "complex_model_with_submaps"; - helper.setUrl("http://test/?id=" + projectId); - var customMap; - var emptySubmodelId = 16730; - var filledSubmodelId = 16731; - var overlayId = 18083; - - return ServerConnector.getProject(projectId).then(function (project) { - var options = helper.createCustomMapOptions(project); - customMap = new CustomMap(options); - - return customMap.openSubmap(emptySubmodelId); - }).then(function () { - return customMap.openSubmap(filledSubmodelId); - }).then(function () { - - var emptySubmap = customMap.getSubmapById(emptySubmodelId); - var filledSubmap = customMap.getSubmapById(filledSubmodelId); - - return customMap.openDataOverlay(overlayId).then(function () { - - assert.equal(1, customMap.selectedLayoutOverlays[overlayId].length); - assert.equal(1, filledSubmap.selectedLayoutOverlays[overlayId].length); - assert.equal(0, emptySubmap.selectedLayoutOverlays[overlayId].length); - - // now hide the layout - - return customMap.hideSelectedLayout(overlayId); - }).then(function () { - assert.equal(0, customMap.selectedLayoutOverlays[overlayId].length); - assert.equal(0, filledSubmap.selectedLayoutOverlays[overlayId].length); - assert.equal(0, emptySubmap.selectedLayoutOverlays[overlayId].length); - }); - - }).then(function () { - return customMap.destroy(); - }); - }); - - it("with submap double opened", function () { - var projectId = "complex_model_with_submaps"; - helper.setUrl("http://test/?id=" + projectId); - var customMap, filledSubmap; - var filledSubmodelId = 16731; - var overlayId = 18083; - - return ServerConnector.getProject(projectId).then(function (project) { - customMap = helper.createCustomMap(project); - return customMap.openSubmap(filledSubmodelId); - }).then(function () { - filledSubmap = customMap.getSubmapById(filledSubmodelId); - return customMap.openDataOverlay(overlayId); - }).then(function () { - assert.equal(1, filledSubmap.selectedLayoutOverlays[overlayId].length); - return customMap.openSubmap(filledSubmodelId); - }).then(function () { - //after opening submap nothing should change - assert.equal(1, filledSubmap.selectedLayoutOverlays[overlayId].length); - }).finally(function () { - return customMap.destroy(); - }); - }); - - it("check if info window content changed", function () { - var project = helper.createProject(); - var layout = helper.createOverlay(); - layout.setInitialized(true); - layout.setInputDataAvailable(true); - project.addDataOverlay(layout); - - var map = helper.createCustomMap(project); - - var alias = helper.createAlias(map); - var ie = helper.createIdentifiedElement(alias); - var marker = map.getMapCanvas().createMarker({icon: "empty.png", position: new Point(0, 0)}); - var infoWindow; - return map.openInfoWindowForIdentifiedElement(ie, marker).then(function (result) { - infoWindow = result; - assert.notOk(infoWindow.getContent().innerHTML.indexOf(layout.getName()) >= 0); - return map.openDataOverlay(layout.getId()); - }).then(function () { - assert.ok(infoWindow.getContent().innerHTML.indexOf(layout.getName()) >= 0); - assert.equal(logger.getErrors().length, 0); - }); - }); - }); - - describe("hideDataOverlay", function () { - it("default", function () { - var map = helper.createCustomMap(); - var layout = helper.createOverlay(); - layout.setInitialized(true); - layout.setInputDataAvailable(true); - map.getProject().addDataOverlay(layout); - - return map.openDataOverlay(layout.getId()).then(function () { - return map.hideDataOverlay(layout.getId()); - }).then(function () { - var vLayouts = ServerConnector.getSessionData(map.getProject()).getVisibleOverlays(); - assert.equal(0, vLayouts.length); - }); - }); - it("check if info window content changed", function () { - var project = helper.createProject(); - var layout = helper.createOverlay(); - layout.setInitialized(true); - layout.setInputDataAvailable(true); - project.addDataOverlay(layout); - - var map = helper.createCustomMap(project); - - var alias = helper.createAlias(map); - var ie = helper.createIdentifiedElement(alias); - var marker = map.getMapCanvas().createMarker({icon: "empty.png", position: new Point(0, 0)}); - var infoWindow; - return map.openInfoWindowForIdentifiedElement(ie, marker).then(function (result) { - infoWindow = result; - return map.openDataOverlay(layout.getId()); - }).then(function () { - assert.ok(infoWindow.getContent().innerHTML.indexOf(layout.getName()) >= 0); - return map.hideDataOverlay(layout.getId()); - }).then(function () { - assert.notOk(infoWindow.getContent().innerHTML.indexOf(layout.getName()) >= 0); - assert.equal(logger.getErrors().length, 0); - }); - }); - }); - - - describe("renderOverlayCollection", function () { - it("for alias", function () { - var map = helper.createCustomMap(); - var alias = helper.createAlias(map); - - var oc = helper.createDbOverlay(map); - - oc.getIdentifiedElements = function () { - return Promise.resolve([new IdentifiedElement({ - objectId: alias.getId(), - icon: "empty.png", - modelId: map.getId(), - type: "Alias" - })]); - }; - return map.renderOverlayCollection({ - overlayCollection: oc - }).then(function () { - var markers = map.getMarkerSurfaceCollection().getMarkers(); - assert.equal(1, markers.length); - }); - }); - - it("alias re-rendering with different icon", function () { - var map = helper.createCustomMap(); - var reaction = helper.createReaction(map, true); - var alias = helper.createAlias(map); - map.getModel().addAlias(alias); - map.getModel().addReaction(reaction); - - var identifiedElement = new IdentifiedElement(alias); - identifiedElement.setIcon("empty.png"); - var identifiedElement2 = new IdentifiedElement(alias); - identifiedElement2.setIcon("new_icon.png"); - - var marker; - var oc = helper.createDbOverlay(map); - - oc.getIdentifiedElements = function () { - return Promise.resolve([identifiedElement, new IdentifiedElement(reaction)]); - }; - return map.renderOverlayCollection({ - overlayCollection: oc - }).then(function () { - marker = map.getMarkerSurfaceCollection().getMarker(identifiedElement); - oc.getIdentifiedElements = function () { - return Promise.resolve([identifiedElement2]); - }; - assert.ok(map.getMarkerSurfaceCollection().getSurface({element: reaction, overlay: oc})); - - return map.renderOverlayCollection({ - overlayCollection: oc - }); - }).then(function () { - assert.equal(marker.getIcon(), "new_icon.png"); - - assert.notOk(oc.mapOverlays["REACTION"][reaction.getId()]); - }); - }); - - it("for set of aliases", function () { - var map = helper.createCustomMap(); - - var oc = helper.createDbOverlay(map); - - var identifiedElements = []; - for (var i = 0; i < 3; i++) { - var alias = helper.createAlias(map); - map.getModel().addAlias(alias); - var ie = helper.createIdentifiedElement(alias); - ie.setIcon(""); - identifiedElements.push(ie); - } - - oc.getIdentifiedElements = function () { - return Promise.resolve(identifiedElements); - }; - - return map.renderOverlayCollection({ - overlayCollection: oc - }).then(function () { - var markers = map.getMarkerSurfaceCollection().getMarkers(); - assert.equal(3, markers.length); - }); - }); - - it("for point", function () { - var map = helper.createCustomMap(); - - var oc = helper.createDbOverlay(map); - - var javaObj = { - objectId: "Point2D.Double[117.685546875, 204.6923828125001]", - modelId: map.getId(), - type: "POINT", - icon: "marker/empty.png" - }; - - oc.getIdentifiedElements = function () { - return Promise.resolve([new IdentifiedElement(javaObj)]); - }; - - return map.renderOverlayCollection({ - overlayCollection: oc - }).then(function () { - var markers = map.getMarkerSurfaceCollection().getMarkers(); - assert.equal(1, markers.length); - }); - }); - - it("for reaction", function () { - var map = helper.createCustomMap(); - var reaction = helper.createReaction(map, true); - map.getModel().addReaction(reaction); - - var oc = helper.createDbOverlay(map); - - oc.getIdentifiedElements = function () { - return Promise.resolve([new IdentifiedElement(reaction)]); - }; - - return map.renderOverlayCollection({ - overlayCollection: oc - }).then(function () { - var surfaces = map.getMarkerSurfaceCollection().getSurfaces(); - assert.equal(1, surfaces.length); - }); - }); - }); - - it("refreshMarkers", function () { - var map = helper.createCustomMap(); - var alias = helper.createAlias(map); - map.getModel().addAlias(alias); - - var oc = helper.createDbOverlay(map); - - oc.getIdentifiedElements = function () { - var element = new IdentifiedElement(alias); - element.setIcon("icon"); - return Promise.resolve([element]); - }; - return map.renderOverlayCollection({ - overlayCollection: oc - }).then(function () { - return map.refreshMarkers(true); - }).then(function () { - var markers = map.getMarkerSurfaceCollection().getMarkers(); - assert.equal(1, markers.length); - }); - }); - - it("clearDbOverlays", function () { - var map = helper.createCustomMap(); - - var oc = helper.createDbOverlay(map); - - var javaObj = { - objectId: "Point2D.Double[117.685546875, 204.6923828125001]", - modelId: map.getId(), - type: "POINT", - icon: "marker/empty.png" - }; - var searchResults = [new IdentifiedElement(javaObj)]; - - oc.getIdentifiedElements = function () { - return Promise.resolve(searchResults); - }; - oc.clear = function () { - searchResults = []; - return this.callListeners("onSearch", searchResults); - }; - - return map.renderOverlayCollection({ - overlayCollection: oc - }).then(function () { - - return map.clearDbOverlays(); - }).then(function () { - var markerCount = 0; - for (var id in oc.pointMarkers) { - if (oc.pointMarkers.hasOwnProperty(id)) { - markerCount++; - } - } - - assert.equal(0, markerCount); - }); - - }); - - it("getInfoWindowForIdentifiedElement ( reaction)", function () { - var map = helper.createCustomMap(); - var reaction = helper.createReaction(map, true); - map.getModel().addReaction(reaction); - - var ie = helper.createIdentifiedElement(reaction); - var marker = map.getMapCanvas().createMarker({icon: "empty.png", position: new Point(0, 0)}); - - var infoWindow = map.getInfoWindowForIdentifiedElement(ie); - - assert.equal(null, infoWindow); - return map.openInfoWindowForIdentifiedElement(ie, marker).then(function () { - infoWindow = map.getInfoWindowForIdentifiedElement(ie); - - assert.ok(infoWindow); - }); - - }); - - it("right click on map", function () { - var map = helper.createCustomMap(); - map.setContextMenu(new MapContextMenu({ - customMap: map, - element: testDiv, - molArt: new MolArt(map.getElement(), map) - })); - - return map.getContextMenu().init().then(function () { - var data = { - stop: null, - point: new Point(10.0, 20.0) - }; - - assert.notOk(map.getActiveSubmapId()); - return map.triggerEvent("map-rightclick", data); - }).then(function () { - //we need to wait because some implementations don't use promises... - return Promise.delay(100); - }).then(function () { - assert.equal(map.getId(), map.getActiveSubmapId()); - return map.destroy(); - }); - - }); - - it("left click on map", function () { - var map; - var searchOverlay; - return ServerConnector.getProject().then(function (project) { - map = helper.createCustomMap(project); - searchOverlay = helper.createSearchDbOverlay(map); - - var data = { - stop: null, - point: new Point(184.79, 365.76) - }; - map.setZoom(4); - - assert.notOk(map.getActiveSubmapId()); - return map.triggerEvent("map-click", data); - }).then(function () { - //we need to wait because some implementations don't use promises... - return Promise.delay(100); - }).then(function () { - assert.equal(map.getId(), map.getActiveSubmapId()); - var element = new IdentifiedElement({id: 329171, type: "ALIAS", modelId: map.getId()}); - assert.ok(map.getMarkerSurfaceCollection().getMarker(element)); - }); - - }); - - it("left click on reaction", function () { - var map; - var searchOverlay; - return ServerConnector.getProject().then(function (project) { - map = helper.createCustomMap(project); - searchOverlay = helper.createSearchDbOverlay(map); - - var data = { - stop: null, - point: new Point(457.51, 356.84) - }; - map.setZoom(4); - - assert.notOk(map.getActiveSubmapId()); - return map.triggerEvent("map-click", data); - }).then(function () { - //we need to wait because some implementations don't use promises... - return Promise.delay(100); - }).then(function () { - assert.equal(map.getId(), map.getActiveSubmapId()); - - var reaction = new IdentifiedElement({id: 153521, type: "REACTION", modelId: map.getId()}); - var surface = map.getMarkerSurfaceCollection().getSurface({element: reaction, overlay: searchOverlay}); - - assert.ok(surface); - assert.ok(surface.isShown()); - - var element = new IdentifiedElement({id: 329165, type: "ALIAS", modelId: map.getId()}); - var marker = map.getMarkerSurfaceCollection().getMarker(element); - assert.ok(marker); - }); - }); - - it("getAliasVisibleLayoutsData", function () { - var mockObject = helper.createCustomMap(); - - var alias = helper.createAlias(); - mockObject.getModel().addAlias(alias); - - var layout = helper.createOverlay(); - layout.setInputDataAvailable(true); - layout.setInitialized(true); - mockObject.getProject().addDataOverlay(layout); - - return mockObject.openDataOverlay(layout.getId()).then(function () { - return mockObject.getAliasVisibleLayoutsData(alias.getId()); - }).then(function (layoutAliases) { - assert.equal(layoutAliases.length, 1); - }); - }); - - it("changed coordinates in map", function () { - var map = helper.createCustomMap(); - var oldCenter = map.getCenter(); - var newCenter = new Point(3, 87); - map.setCenter(newCenter); - map.triggerEvent("map-center_changed"); - - var center = ServerConnector.getSessionData(map.getProject()).getCenter(map.getModel()); - assert.ok(center !== oldCenter); - assert.ok(center instanceof Point); - }); - - it("refreshComments", function () { - var map = helper.createCustomMap(); - map.getModel().setId(15781); - helper.createCommentDbOverlay(map); - - ServerConnector.getSessionData().setShowComments(true); - return map.refreshComments().then(function () { - assert.notOk(map.getMarkerSurfaceCollection().getMarker(new IdentifiedElement({ - id: '(241.01,372.35)', - modelId: map.getId(), - type: "POINT" - }))); - assert.ok(map.getMarkerSurfaceCollection().getMarker(new IdentifiedElement({ - id: '(643.96,144.09)', - modelId: map.getId(), - type: "POINT" - }))); - assert.notOk(map.getMarkerSurfaceCollection().getMarker(new IdentifiedElement({ - id: '(216.65,370.00)', - modelId: map.getId(), - type: "POINT" - }))); - assert.notOk(map.getMarkerSurfaceCollection().getMarker(new IdentifiedElement({ - id: 'unkId', - modelId: map.getId(), - type: "POINT" - }))); - }); - }); - - it("hide comments", function () { - var map = helper.createCustomMap(); - map.getModel().setId(15781); - helper.createCommentDbOverlay(map); - - ServerConnector.getSessionData().setShowComments(true); - return map.refreshComments().then(function () { - ServerConnector.getSessionData().setShowComments(false); - return map.refreshComments(); - }).then(function () { - assert.notOk(map.getMarkerSurfaceCollection().getMarker(new IdentifiedElement({ - id: '(241.01, 372.35)', - modelId: map.getId(), - type: "POINT" - }))); - }); - }); - - it("openCommentDialog", function () { - var map = helper.createCustomMap(); - map.getModel().setId(15781); - map.setActiveSubmapId(15781); - map.setActiveSubmapClickCoordinates(new Point(2, 12)); - return map.openCommentDialog().then(function () { - var types = map.getCommentDialog().getTypes(); - assert.equal(types.length, 6); - var selected = map.getCommentDialog().getSelectedType(); - assert.ok(selected === "<General>"); - - map.getCommentDialog().setSelectedType(1); - selected = map.getCommentDialog().getSelectedType(); - assert.notOk(selected === "<General>"); - - map.getCommentDialog().setSelectedType(2); - selected = map.getCommentDialog().getSelectedType(); - assert.notOk(selected === "<General>"); - }).then(function () { - map.getCommentDialog().destroy(); - }); - }); - - describe("addComment", function () { - it("default", function () { - var map; - return ServerConnector.getProject().then(function (project) { - map = helper.createCustomMap(project); - helper.createCommentDbOverlay(map); - map.setActiveSubmapId(map.getId()); - map.setActiveSubmapClickCoordinates(new Point(2, 12)); - return map.openCommentDialog(); - }).then(function () { - return map.getCommentDialog().addComment(); - }).then(function (comments) { - assert.equal(0, comments.length); - map.getCommentDialog().destroy(); - }); - }); - - it("when comments are visible", function () { - var map; - return ServerConnector.getProject().then(function (project) { - map = helper.createCustomMap(project); - helper.createCommentDbOverlay(map); - map.setActiveSubmapId(map.getId()); - map.setActiveSubmapClickCoordinates(new Point(2, 12)); - return map.openCommentDialog(); - }).then(function () { - ServerConnector.getSessionData().setShowComments(true); - return map.getCommentDialog().addComment(); - }).then(function (comments) { - assert.ok(comments.length > 0); - map.getCommentDialog().destroy(); - }); - }); - - it("add for protein", function () { - var map; - return ServerConnector.getProject().then(function (project) { - map = helper.createCustomMap(project); - helper.createCommentDbOverlay(map); - map.setActiveSubmapId(map.getId()); - map.setActiveSubmapClickCoordinates(new Point(2, 12)); - return map.openCommentDialog(); - }).then(function () { - var dialog = map.getCommentDialog(); - dialog.setSelectedType(1); - return dialog.addComment(); - }).then(function () { - map.getCommentDialog().destroy(); - }); - }); - }); - - it("retrieveOverlayDetailDataForElement for comment", function () { - var map = helper.createCustomMap(); - helper.createCommentDbOverlay(map); - - var alias = helper.createAlias(map); - alias.setId(329157); - map.getModel().addAlias(alias); - - var ie = new IdentifiedElement(alias); - - return map.retrieveOverlayDetailDataForElement(ie, { - comment: true - }).then(function (details) { - assert.ok(details); - assert.equal(details.length, 1); - assert.equal(details[0].length, 1); - assert.ok(details[0][0] instanceof Comment); - }); - }); - - it("getOverlayDataForIdentifiedElement", function () { - var map = helper.createCustomMap(); - var commentOverlay = helper.createCommentDbOverlay(map); - - var alias = helper.createAlias(map); - alias.setId(329157); - map.getModel().addAlias(alias); - - var ie = new IdentifiedElement(alias); - - return map.getOverlayDataForIdentifiedElement(ie, { - comment: true - }).then(function (details) { - assert.equal(details.length, 1); - - var overlayData = details[0]; - assert.equal(overlayData.overlay, commentOverlay); - assert.ok(overlayData.data); - assert.equal(overlayData.data.length, 1); - assert.ok(overlayData.data[0] instanceof Comment); - }); - }); - - it("openSubmap", function () { - var options = helper.createCustomMapOptions(); - - var submodel = helper.createModel(); - options.getProject().addModel(submodel); - - var map = new CustomMap(options); - - map.openSubmap(submodel.getId()); - map.destroy(); - }); - - describe("setCenter", function () { - it("default", function () { - var options = helper.createCustomMapOptions(); - - var map = new CustomMap(options); - - map.setCenter(new Point(10, 20)); - assert.ok(ServerConnector.getSessionData().getCenter(map.getModel())); - }); - - it("on submap", function () { - var options = helper.createCustomMapOptions(); - - var submodel = helper.createModel(); - options.getProject().addModel(submodel); - - var map = new CustomMap(options); - map.openSubmap(submodel.getId()); - var submap = map.getSubmapById(submodel.getId()); - submap.setCenter(new Point(10, 20)); - assert.ok(ServerConnector.getSessionData().getCenter(submodel)); - map.destroy(); - }); - }); - - it("setZoom", function () { - var options = helper.createCustomMapOptions(); - - var map = new CustomMap(options); - - map.setZoom(3); - assert.equal(3, ServerConnector.getSessionData().getZoomLevel(map.getModel())); - }); - - it("removeSelection when invalid model selected", function () { - var options = helper.createCustomMapOptions(); - - var map = new CustomMap(options); - map.setActiveSubmapId(-1); - - try { - map.removeSelection(); - assert.ok(false); - } catch (e) { - assert.ok(e.message.indexOf("Cannot find submap") >= 0); - } - }); - - describe("_openInfoWindowForIdentifiedElement", function () { - it("for AliasMarker", function () { - var map; - var alias, marker; - return ServerConnector.getProject().then(function (project) { - map = helper.createCustomMap(project); - return map.getModel().getAliasById(329171); - }).then(function (result) { - alias = result; - - var identifiedElement = new IdentifiedElement(alias); - identifiedElement.setIcon("empty.png"); - - marker = new AliasMarker({ - element: identifiedElement, - map: map - }); - - return marker.init(); - }).then(function () { - assert.equal(null, map.getAliasInfoWindowById(alias.getId())); - return map._openInfoWindowForIdentifiedElement(marker).then(function () { - assert.ok(map.getAliasInfoWindowById(alias.getId())); - }); - }); - - }); - it("for ReactionMarker", function () { - var map; - var reaction, marker; - return ServerConnector.getProject().then(function (project) { - map = helper.createCustomMap(project); - return map.getModel().getReactionById(153510); - }).then(function (result) { - reaction = result; - - marker = new ReactionMarker({ - element: new IdentifiedElement(reaction), - map: map - }); - return marker.init(); - }).then(function () { - assert.equal(null, map.getReactionInfoWindowById(reaction.getId())); - return map._openInfoWindowForIdentifiedElement(marker); - }).then(function () { - assert.ok(map.getReactionInfoWindowById(reaction.getId())); - }); - - }); - it("for PointMarker", function () { - - var mockObject = helper.createCustomMap(); - - mockObject.getOverlayDataForPoint = function () { - return Promise.resolve([]); - }; - - var point = new Point(2, 3.45); - var pointData = new PointData(point, mockObject.getId()); - - var pointMarker = new PointMarker({ - element: new IdentifiedElement(pointData), - map: mockObject - }); - - return pointMarker.init().then(function () { - assert.equal(null, mockObject.getPointInfoWindowById(pointData.getId())); - return mockObject._openInfoWindowForIdentifiedElement(pointMarker.getIdentifiedElement()); - }).then(function () { - assert.ok(mockObject.getPointInfoWindowById(pointData.getId())); - }); - }); - }); - - describe("init", function () { - it("invalid background overlay", function () { - var options = helper.createCustomMapOptions(); - ServerConnector.getSessionData(options.getProject()).setSelectedBackgroundOverlay("bla"); - var map = new CustomMap(options); - return map.init().then(function () { - assert.false("Error expected"); - }, function () { - map.destroy(); - }) - }); - - it("non-existing background overlay", function () { - var options = helper.createCustomMapOptions(); - ServerConnector.getSessionData(options.getProject()).setSelectedBackgroundOverlay(-1); - var map = new CustomMap(options); - return map.init().then(function () { - assert.ok(ServerConnector.getSessionData(options.getProject()).getSelectedBackgroundOverlay() > 0); - return map.destroy(); - }) - }); - - it("with session data overlays", function () { - var project = helper.createProject(); - var overlay1 = helper.createOverlay(); - overlay1.setInputDataAvailable(true); - project.addDataOverlay(overlay1); - - var options = helper.createCustomMapOptions(project); - ServerConnector.getSessionData(options.getProject()).setVisibleOverlays([overlay1.getId()]); - var map = new CustomMap(options); - return map.init().then(function () { - return map.getVisibleDataOverlays(); - }).then(function (overlays) { - assert.equal(1, overlays.length); - map.destroy(); - }) - }); - - }); - - describe("appendElementsPointingToSubmap", function () { - it("point to reaction", function () { - helper.setUrl("http://test/?id=complex_model_with_submaps"); - return ServerConnector.getProject().then(function (project) { - var map = helper.createCustomMap(project); - var oc = helper.createSearchDbOverlay(map); - - var reaction = new IdentifiedElement({id: 161955, modelId: 16729, type: "REACTION"}); - - return map.appendElementsPointingToSubmap([reaction], oc).then(function (elements) { - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - //alias pointing to reaction should have an icon - if (element.type === "ALIAS") { - assert.ok(element.getIcon() !== undefined); - } - } - }); - }); - }); - }); - describe("logo link", function () { - it("left logo click", function () { - var map = helper.createCustomMap(); - return map.getControl(ControlType.LOGO_2_IMG).onclick() - }); - it("right logo click", function () { - var map = helper.createCustomMap(); - return map.getControl(ControlType.LOGO_IMG).onclick() - }); - }); -}); +"use strict"; + +var Promise = require("bluebird"); + +require("../mocha-config.js"); + +var AliasMarker = require('../../../main/js/map/marker/AliasMarker'); +var AliasSurface = require('../../../main/js/map/surface/AliasSurface'); +var Comment = require('../../../main/js/map/data/Comment'); +var ControlType = require('../../../main/js/map/ControlType'); +var CustomMap = require('../../../main/js/map/CustomMap'); +var IdentifiedElement = require('../../../main/js/map/data/IdentifiedElement'); +var MapContextMenu = require('../../../main/js/gui/MapContextMenu'); +var MolArt = require('../../../main/js/map/structure/MolArt'); +var Point = require('../../../main/js/map/canvas/Point'); +var PointData = require('../../../main/js/map/data/PointData'); +var PointMarker = require('../../../main/js/map/marker/PointMarker'); +var ReactionMarker = require('../../../main/js/map/marker/ReactionMarker'); +var ReactionSurface = require('../../../main/js/map/surface/ReactionSurface'); + +var ServerConnector = require('./../ServerConnector-mock'); + +var logger = require('./../logger'); + +var chai = require('chai'); +var assert = chai.assert; + +describe('CustomMap', function () { + describe("constructor", function () { + it("default", function () { + var options = helper.createCustomMapOptions(); + var map = new CustomMap(options); + assert.ok(map); + }); + + it("with submaps", function () { + var options = helper.createCustomMapOptions(); + + options.getProject().addModel(helper.createModel()); + + var map = new CustomMap(options); + assert.ok(map); + }); + + it("with session data pointing to not existing overlay", function () { + var options = helper.createCustomMapOptions(); + + ServerConnector.getSessionData(options.getProject()).setSelectedBackgroundOverlay("-1"); + + var map = new CustomMap(options); + assert.ok(map); + }); + }); + + it("getSubmapById", function () { + var map = helper.createCustomMap(); + assert.ok(map.getSubmapById(map.getId())); + }); + + it("getSubmapById (invalid)", function () { + var map = helper.createCustomMap(); + assert.equal(map.getSubmapById(-1), null); + }); + + it("getSubmapById (string id)", function () { + var map = helper.createCustomMap(); + assert.ok(map.getSubmapById(map.getId() + "")); + }); + + describe("openDataOverlay", function () { + it("for not existing id", function () { + var map = helper.createCustomMap(); + try { + map.openDataOverlay(-1); + assert.ok(false); + } catch (exception) { + assert.ok(exception.message.indexOf("You have no privileges") >= 0); + } + }); + + it("for int id", function () { + var options = helper.createCustomMapOptions(); + var layout = options.getProject().getDataOverlays()[0]; + var map = new CustomMap(options); + map.openDataOverlay(layout.getId()); + assert.equal(logger.getErrors().length, 0); + }); + + it("for overlay object", function () { + var options = helper.createCustomMapOptions(); + var layout = options.getProject().getDataOverlays()[0]; + var map = new CustomMap(options); + map.openDataOverlay(layout); + assert.equal(logger.getErrors().length, 0); + }); + + it("for string id", function () { + var options = helper.createCustomMapOptions(); + var layout = options.getProject().getDataOverlays()[0]; + var map = new CustomMap(options); + map.openDataOverlay(layout.getId() + ""); + assert.equal(logger.getErrors().length, 0); + }); + + it("with background overlay", function () { + var map = helper.createCustomMap(); + var layout = helper.createOverlay(); + layout.setInitialized(true); + layout.setInputDataAvailable(false); + map.getProject().addDataOverlay(layout); + + return map.openDataOverlay(layout.getId()).then(function () { + var vLayouts = ServerConnector.getSessionData(map.getProject()).getVisibleOverlays(); + assert.equal(0, vLayouts.length); + }); + }); + + it("with non background overlay", function () { + var project = helper.createProject(); + var layout = helper.createOverlay(); + layout.setInitialized(true); + layout.setInputDataAvailable(true); + project.addDataOverlay(layout); + + var emptyBackground = helper.createOverlay(); + emptyBackground.setInputDataAvailable(false); + emptyBackground.setName("Empty"); + project.addDataOverlay(emptyBackground); + + var map = helper.createCustomMap(project); + + + return map.openDataOverlay(layout.getId()).then(function () { + var backgroundId = ServerConnector.getSessionData(project).getSelectedBackgroundOverlay(); + assert.equal(backgroundId, emptyBackground.getId()); + }); + }); + + it("check backgroundChangeListener", function () { + var project = helper.createProject(); + var overlay = helper.createOverlay(); + overlay.setInitialized(true); + overlay.setInputDataAvailable(true); + project.addDataOverlay(overlay); + + var overlay2 = helper.createOverlay(); + overlay2.setInitialized(true); + overlay2.setInputDataAvailable(true); + project.addDataOverlay(overlay2); + + var emptyBackground = helper.createOverlay(); + emptyBackground.setInputDataAvailable(false); + emptyBackground.setName("Empty"); + project.addDataOverlay(emptyBackground); + + var map = helper.createCustomMap(project); + + var counter = 0; + map.addListener("onBackgroundOverlayChange", function () { + counter++; + }); + + return map.openDataOverlay(overlay.getId()).then(function () { + assert.equal(1, counter, "listener wasn't fired"); + return map.openDataOverlay(overlay2.getId()); + }).then(function () { + assert.equal(1, counter, "listener shouldn't be fired again because nothing changed"); + }); + }); + + it("simple", function () { + var map = helper.createCustomMap(); + var alias = helper.createAlias(map); + map.getModel().addAlias(alias); + + var reaction = helper.createReaction(map); + map.getModel().addReaction(reaction); + + var layout = helper.createOverlay(); + layout.setInputDataAvailable(true); + layout.setInitialized(true); + var layoutAlias = helper.createLayoutAlias(alias); + layout.addAlias(layoutAlias); + + var layoutReaction = helper.createLayoutReaction(reaction); + layout.addReaction(layoutReaction); + + map.getProject().addDataOverlay(layout); + + return map.openDataOverlay(layout.getId()).then(function () { + return map._showSelectedDataOverlay(layout.getId(), 0, 1); + }).then(function () { + var vLayouts = ServerConnector.getSessionData(map.getProject()).getVisibleOverlays(); + assert.equal(1, vLayouts.length); + assert.equal(layout.getId(), vLayouts[0]); + + assert.equal(2, map.selectedLayoutOverlays[layout.getId()].length); + var surface1 = map.selectedLayoutOverlays[layout.getId()][0]; + var surface2 = map.selectedLayoutOverlays[layout.getId()][1]; + assert.ok(surface1 instanceof AliasSurface || surface2 instanceof AliasSurface); + assert.ok(surface1 instanceof ReactionSurface || surface2 instanceof ReactionSurface); + + // now hide the layout + return map._hideSelectedLayout(layout.getId()); + }).then(function () { + assert.ok(map.selectedLayoutOverlays[layout.getId()]); + assert.equal(0, map.selectedLayoutOverlays[layout.getId()].length); + }); + + }); + + it("with submaps", function () { + var projectId = "complex_model_with_submaps"; + helper.setUrl("http://test/?id=" + projectId); + var customMap; + var emptySubmodelId = 16730; + var filledSubmodelId = 16731; + var overlayId = 18083; + + return ServerConnector.getProject(projectId).then(function (project) { + var options = helper.createCustomMapOptions(project); + customMap = new CustomMap(options); + + return customMap.openSubmap(emptySubmodelId); + }).then(function () { + return customMap.openSubmap(filledSubmodelId); + }).then(function () { + + var emptySubmap = customMap.getSubmapById(emptySubmodelId); + var filledSubmap = customMap.getSubmapById(filledSubmodelId); + + return customMap.openDataOverlay(overlayId).then(function () { + + assert.equal(2, customMap.selectedLayoutOverlays[overlayId].length); + assert.equal(1, filledSubmap.selectedLayoutOverlays[overlayId].length); + assert.equal(0, emptySubmap.selectedLayoutOverlays[overlayId].length); + + // now hide the layout + + return customMap.hideSelectedLayout(overlayId); + }).then(function () { + assert.equal(0, customMap.selectedLayoutOverlays[overlayId].length); + assert.equal(0, filledSubmap.selectedLayoutOverlays[overlayId].length); + assert.equal(0, emptySubmap.selectedLayoutOverlays[overlayId].length); + }); + + }).then(function () { + return customMap.destroy(); + }); + }); + + it("with submap double opened", function () { + var projectId = "complex_model_with_submaps"; + helper.setUrl("http://test/?id=" + projectId); + var customMap, filledSubmap; + var filledSubmodelId = 16731; + var overlayId = 18083; + + return ServerConnector.getProject(projectId).then(function (project) { + customMap = helper.createCustomMap(project); + return customMap.openSubmap(filledSubmodelId); + }).then(function () { + filledSubmap = customMap.getSubmapById(filledSubmodelId); + return customMap.openDataOverlay(overlayId); + }).then(function () { + assert.equal(1, filledSubmap.selectedLayoutOverlays[overlayId].length); + return customMap.openSubmap(filledSubmodelId); + }).then(function () { + //after opening submap nothing should change + assert.equal(1, filledSubmap.selectedLayoutOverlays[overlayId].length); + }).finally(function () { + return customMap.destroy(); + }); + }); + + it("check if info window content changed", function () { + var project = helper.createProject(); + var layout = helper.createOverlay(); + layout.setInitialized(true); + layout.setInputDataAvailable(true); + project.addDataOverlay(layout); + + var map = helper.createCustomMap(project); + + var alias = helper.createAlias(map); + var ie = helper.createIdentifiedElement(alias); + var marker = map.getMapCanvas().createMarker({icon: "empty.png", position: new Point(0, 0)}); + var infoWindow; + return map.openInfoWindowForIdentifiedElement(ie, marker).then(function (result) { + infoWindow = result; + assert.notOk(infoWindow.getContent().innerHTML.indexOf(layout.getName()) >= 0); + return map.openDataOverlay(layout.getId()); + }).then(function () { + assert.ok(infoWindow.getContent().innerHTML.indexOf(layout.getName()) >= 0); + assert.equal(logger.getErrors().length, 0); + }); + }); + }); + + describe("hideDataOverlay", function () { + it("default", function () { + var map = helper.createCustomMap(); + var layout = helper.createOverlay(); + layout.setInitialized(true); + layout.setInputDataAvailable(true); + map.getProject().addDataOverlay(layout); + + return map.openDataOverlay(layout.getId()).then(function () { + return map.hideDataOverlay(layout.getId()); + }).then(function () { + var vLayouts = ServerConnector.getSessionData(map.getProject()).getVisibleOverlays(); + assert.equal(0, vLayouts.length); + }); + }); + it("check if info window content changed", function () { + var project = helper.createProject(); + var layout = helper.createOverlay(); + layout.setInitialized(true); + layout.setInputDataAvailable(true); + project.addDataOverlay(layout); + + var map = helper.createCustomMap(project); + + var alias = helper.createAlias(map); + var ie = helper.createIdentifiedElement(alias); + var marker = map.getMapCanvas().createMarker({icon: "empty.png", position: new Point(0, 0)}); + var infoWindow; + return map.openInfoWindowForIdentifiedElement(ie, marker).then(function (result) { + infoWindow = result; + return map.openDataOverlay(layout.getId()); + }).then(function () { + assert.ok(infoWindow.getContent().innerHTML.indexOf(layout.getName()) >= 0); + return map.hideDataOverlay(layout.getId()); + }).then(function () { + assert.notOk(infoWindow.getContent().innerHTML.indexOf(layout.getName()) >= 0); + assert.equal(logger.getErrors().length, 0); + }); + }); + }); + + + describe("renderOverlayCollection", function () { + it("for alias", function () { + var map = helper.createCustomMap(); + var alias = helper.createAlias(map); + + var oc = helper.createDbOverlay(map); + + oc.getIdentifiedElements = function () { + return Promise.resolve([new IdentifiedElement({ + objectId: alias.getId(), + icon: "empty.png", + modelId: map.getId(), + type: "Alias" + })]); + }; + return map.renderOverlayCollection({ + overlayCollection: oc + }).then(function () { + var markers = map.getMarkerSurfaceCollection().getMarkers(); + assert.equal(1, markers.length); + }); + }); + + it("alias re-rendering with different icon", function () { + var map = helper.createCustomMap(); + var reaction = helper.createReaction(map, true); + var alias = helper.createAlias(map); + map.getModel().addAlias(alias); + map.getModel().addReaction(reaction); + + var identifiedElement = new IdentifiedElement(alias); + identifiedElement.setIcon("empty.png"); + var identifiedElement2 = new IdentifiedElement(alias); + identifiedElement2.setIcon("new_icon.png"); + + var marker; + var oc = helper.createDbOverlay(map); + + oc.getIdentifiedElements = function () { + return Promise.resolve([identifiedElement, new IdentifiedElement(reaction)]); + }; + return map.renderOverlayCollection({ + overlayCollection: oc + }).then(function () { + marker = map.getMarkerSurfaceCollection().getMarker(identifiedElement); + oc.getIdentifiedElements = function () { + return Promise.resolve([identifiedElement2]); + }; + assert.ok(map.getMarkerSurfaceCollection().getSurface({element: reaction, overlay: oc})); + + return map.renderOverlayCollection({ + overlayCollection: oc + }); + }).then(function () { + assert.equal(marker.getIcon(), "new_icon.png"); + + assert.notOk(oc.mapOverlays["REACTION"][reaction.getId()]); + }); + }); + + it("for set of aliases", function () { + var map = helper.createCustomMap(); + + var oc = helper.createDbOverlay(map); + + var identifiedElements = []; + for (var i = 0; i < 3; i++) { + var alias = helper.createAlias(map); + map.getModel().addAlias(alias); + var ie = helper.createIdentifiedElement(alias); + ie.setIcon(""); + identifiedElements.push(ie); + } + + oc.getIdentifiedElements = function () { + return Promise.resolve(identifiedElements); + }; + + return map.renderOverlayCollection({ + overlayCollection: oc + }).then(function () { + var markers = map.getMarkerSurfaceCollection().getMarkers(); + assert.equal(3, markers.length); + }); + }); + + it("for point", function () { + var map = helper.createCustomMap(); + + var oc = helper.createDbOverlay(map); + + var javaObj = { + objectId: "Point2D.Double[117.685546875, 204.6923828125001]", + modelId: map.getId(), + type: "POINT", + icon: "marker/empty.png" + }; + + oc.getIdentifiedElements = function () { + return Promise.resolve([new IdentifiedElement(javaObj)]); + }; + + return map.renderOverlayCollection({ + overlayCollection: oc + }).then(function () { + var markers = map.getMarkerSurfaceCollection().getMarkers(); + assert.equal(1, markers.length); + }); + }); + + it("for reaction", function () { + var map = helper.createCustomMap(); + var reaction = helper.createReaction(map, true); + map.getModel().addReaction(reaction); + + var oc = helper.createDbOverlay(map); + + oc.getIdentifiedElements = function () { + return Promise.resolve([new IdentifiedElement(reaction)]); + }; + + return map.renderOverlayCollection({ + overlayCollection: oc + }).then(function () { + var surfaces = map.getMarkerSurfaceCollection().getSurfaces(); + assert.equal(1, surfaces.length); + }); + }); + }); + + it("refreshMarkers", function () { + var map = helper.createCustomMap(); + var alias = helper.createAlias(map); + map.getModel().addAlias(alias); + + var oc = helper.createDbOverlay(map); + + oc.getIdentifiedElements = function () { + var element = new IdentifiedElement(alias); + element.setIcon("icon"); + return Promise.resolve([element]); + }; + return map.renderOverlayCollection({ + overlayCollection: oc + }).then(function () { + return map.refreshMarkers(true); + }).then(function () { + var markers = map.getMarkerSurfaceCollection().getMarkers(); + assert.equal(1, markers.length); + }); + }); + + it("clearDbOverlays", function () { + var map = helper.createCustomMap(); + + var oc = helper.createDbOverlay(map); + + var javaObj = { + objectId: "Point2D.Double[117.685546875, 204.6923828125001]", + modelId: map.getId(), + type: "POINT", + icon: "marker/empty.png" + }; + var searchResults = [new IdentifiedElement(javaObj)]; + + oc.getIdentifiedElements = function () { + return Promise.resolve(searchResults); + }; + oc.clear = function () { + searchResults = []; + return this.callListeners("onSearch", searchResults); + }; + + return map.renderOverlayCollection({ + overlayCollection: oc + }).then(function () { + + return map.clearDbOverlays(); + }).then(function () { + var markerCount = 0; + for (var id in oc.pointMarkers) { + if (oc.pointMarkers.hasOwnProperty(id)) { + markerCount++; + } + } + + assert.equal(0, markerCount); + }); + + }); + + it("getInfoWindowForIdentifiedElement ( reaction)", function () { + var map = helper.createCustomMap(); + var reaction = helper.createReaction(map, true); + map.getModel().addReaction(reaction); + + var ie = helper.createIdentifiedElement(reaction); + var marker = map.getMapCanvas().createMarker({icon: "empty.png", position: new Point(0, 0)}); + + var infoWindow = map.getInfoWindowForIdentifiedElement(ie); + + assert.equal(null, infoWindow); + return map.openInfoWindowForIdentifiedElement(ie, marker).then(function () { + infoWindow = map.getInfoWindowForIdentifiedElement(ie); + + assert.ok(infoWindow); + }); + + }); + + it("right click on map", function () { + var map = helper.createCustomMap(); + map.setContextMenu(new MapContextMenu({ + customMap: map, + element: testDiv, + molArt: new MolArt(map.getElement(), map) + })); + + return map.getContextMenu().init().then(function () { + var data = { + stop: null, + point: new Point(10.0, 20.0) + }; + + assert.notOk(map.getActiveSubmapId()); + return map.triggerEvent("map-rightclick", data); + }).then(function () { + //we need to wait because some implementations don't use promises... + return Promise.delay(100); + }).then(function () { + assert.equal(map.getId(), map.getActiveSubmapId()); + return map.destroy(); + }); + + }); + + it("left click on map", function () { + var map; + var searchOverlay; + return ServerConnector.getProject().then(function (project) { + map = helper.createCustomMap(project); + searchOverlay = helper.createSearchDbOverlay(map); + + var data = { + stop: null, + point: new Point(184.79, 365.76) + }; + map.setZoom(4); + + assert.notOk(map.getActiveSubmapId()); + return map.triggerEvent("map-click", data); + }).then(function () { + //we need to wait because some implementations don't use promises... + return Promise.delay(100); + }).then(function () { + assert.equal(map.getId(), map.getActiveSubmapId()); + var element = new IdentifiedElement({id: 329171, type: "ALIAS", modelId: map.getId()}); + assert.ok(map.getMarkerSurfaceCollection().getMarker(element)); + }); + + }); + + it("left click on reaction", function () { + var map; + var searchOverlay; + return ServerConnector.getProject().then(function (project) { + map = helper.createCustomMap(project); + searchOverlay = helper.createSearchDbOverlay(map); + + var data = { + stop: null, + point: new Point(457.51, 356.84) + }; + map.setZoom(4); + + assert.notOk(map.getActiveSubmapId()); + return map.triggerEvent("map-click", data); + }).then(function () { + //we need to wait because some implementations don't use promises... + return Promise.delay(100); + }).then(function () { + assert.equal(map.getId(), map.getActiveSubmapId()); + + var reaction = new IdentifiedElement({id: 153521, type: "REACTION", modelId: map.getId()}); + var surface = map.getMarkerSurfaceCollection().getSurface({element: reaction, overlay: searchOverlay}); + + assert.ok(surface); + assert.ok(surface.isShown()); + + var element = new IdentifiedElement({id: 329165, type: "ALIAS", modelId: map.getId()}); + var marker = map.getMarkerSurfaceCollection().getMarker(element); + assert.ok(marker); + }); + }); + + it("changed coordinates in map", function () { + var map = helper.createCustomMap(); + var oldCenter = map.getCenter(); + var newCenter = new Point(3, 87); + map.setCenter(newCenter); + map.triggerEvent("map-center_changed"); + + var center = ServerConnector.getSessionData(map.getProject()).getCenter(map.getModel()); + assert.ok(center !== oldCenter); + assert.ok(center instanceof Point); + }); + + it("refreshComments", function () { + var map = helper.createCustomMap(); + map.getModel().setId(15781); + helper.createCommentDbOverlay(map); + + ServerConnector.getSessionData().setShowComments(true); + return map.refreshComments().then(function () { + assert.notOk(map.getMarkerSurfaceCollection().getMarker(new IdentifiedElement({ + id: '(241.01,372.35)', + modelId: map.getId(), + type: "POINT" + }))); + assert.ok(map.getMarkerSurfaceCollection().getMarker(new IdentifiedElement({ + id: '(643.96,144.09)', + modelId: map.getId(), + type: "POINT" + }))); + assert.notOk(map.getMarkerSurfaceCollection().getMarker(new IdentifiedElement({ + id: '(216.65,370.00)', + modelId: map.getId(), + type: "POINT" + }))); + assert.notOk(map.getMarkerSurfaceCollection().getMarker(new IdentifiedElement({ + id: 'unkId', + modelId: map.getId(), + type: "POINT" + }))); + }); + }); + + it("hide comments", function () { + var map = helper.createCustomMap(); + map.getModel().setId(15781); + helper.createCommentDbOverlay(map); + + ServerConnector.getSessionData().setShowComments(true); + return map.refreshComments().then(function () { + ServerConnector.getSessionData().setShowComments(false); + return map.refreshComments(); + }).then(function () { + assert.notOk(map.getMarkerSurfaceCollection().getMarker(new IdentifiedElement({ + id: '(241.01, 372.35)', + modelId: map.getId(), + type: "POINT" + }))); + }); + }); + + it("openCommentDialog", function () { + var map = helper.createCustomMap(); + map.getModel().setId(15781); + map.setActiveSubmapId(15781); + map.setActiveSubmapClickCoordinates(new Point(2, 12)); + return map.openCommentDialog().then(function () { + var types = map.getCommentDialog().getTypes(); + assert.equal(types.length, 6); + var selected = map.getCommentDialog().getSelectedType(); + assert.ok(selected === "<General>"); + + map.getCommentDialog().setSelectedType(1); + selected = map.getCommentDialog().getSelectedType(); + assert.notOk(selected === "<General>"); + + map.getCommentDialog().setSelectedType(2); + selected = map.getCommentDialog().getSelectedType(); + assert.notOk(selected === "<General>"); + }).then(function () { + map.getCommentDialog().destroy(); + }); + }); + + describe("addComment", function () { + it("default", function () { + var map; + return ServerConnector.getProject().then(function (project) { + map = helper.createCustomMap(project); + helper.createCommentDbOverlay(map); + map.setActiveSubmapId(map.getId()); + map.setActiveSubmapClickCoordinates(new Point(2, 12)); + return map.openCommentDialog(); + }).then(function () { + return map.getCommentDialog().addComment(); + }).then(function (comments) { + assert.equal(0, comments.length); + map.getCommentDialog().destroy(); + }); + }); + + it("when comments are visible", function () { + var map; + return ServerConnector.getProject().then(function (project) { + map = helper.createCustomMap(project); + helper.createCommentDbOverlay(map); + map.setActiveSubmapId(map.getId()); + map.setActiveSubmapClickCoordinates(new Point(2, 12)); + return map.openCommentDialog(); + }).then(function () { + ServerConnector.getSessionData().setShowComments(true); + return map.getCommentDialog().addComment(); + }).then(function (comments) { + assert.ok(comments.length > 0); + map.getCommentDialog().destroy(); + }); + }); + + it("add for protein", function () { + var map; + return ServerConnector.getProject().then(function (project) { + map = helper.createCustomMap(project); + helper.createCommentDbOverlay(map); + map.setActiveSubmapId(map.getId()); + map.setActiveSubmapClickCoordinates(new Point(2, 12)); + return map.openCommentDialog(); + }).then(function () { + var dialog = map.getCommentDialog(); + dialog.setSelectedType(1); + return dialog.addComment(); + }).then(function () { + map.getCommentDialog().destroy(); + }); + }); + }); + + it("retrieveOverlayDetailDataForElement for comment", function () { + var map = helper.createCustomMap(); + helper.createCommentDbOverlay(map); + + var alias = helper.createAlias(map); + alias.setId(329157); + map.getModel().addAlias(alias); + + var ie = new IdentifiedElement(alias); + + return map.retrieveOverlayDetailDataForElement(ie, { + comment: true + }).then(function (details) { + assert.ok(details); + assert.equal(details.length, 1); + assert.equal(details[0].length, 1); + assert.ok(details[0][0] instanceof Comment); + }); + }); + + it("getOverlayDataForIdentifiedElement", function () { + var map = helper.createCustomMap(); + var commentOverlay = helper.createCommentDbOverlay(map); + + var alias = helper.createAlias(map); + alias.setId(329157); + map.getModel().addAlias(alias); + + var ie = new IdentifiedElement(alias); + + return map.getOverlayDataForIdentifiedElement(ie, { + comment: true + }).then(function (details) { + assert.equal(details.length, 1); + + var overlayData = details[0]; + assert.equal(overlayData.overlay, commentOverlay); + assert.ok(overlayData.data); + assert.equal(overlayData.data.length, 1); + assert.ok(overlayData.data[0] instanceof Comment); + }); + }); + + it("openSubmap", function () { + var options = helper.createCustomMapOptions(); + + var submodel = helper.createModel(); + options.getProject().addModel(submodel); + + var map = new CustomMap(options); + + map.openSubmap(submodel.getId()); + map.destroy(); + }); + + describe("setCenter", function () { + it("default", function () { + var options = helper.createCustomMapOptions(); + + var map = new CustomMap(options); + + map.setCenter(new Point(10, 20)); + assert.ok(ServerConnector.getSessionData().getCenter(map.getModel())); + }); + + it("on submap", function () { + var options = helper.createCustomMapOptions(); + + var submodel = helper.createModel(); + options.getProject().addModel(submodel); + + var map = new CustomMap(options); + map.openSubmap(submodel.getId()); + var submap = map.getSubmapById(submodel.getId()); + submap.setCenter(new Point(10, 20)); + assert.ok(ServerConnector.getSessionData().getCenter(submodel)); + map.destroy(); + }); + }); + + it("setZoom", function () { + var options = helper.createCustomMapOptions(); + + var map = new CustomMap(options); + + map.setZoom(3); + assert.equal(3, ServerConnector.getSessionData().getZoomLevel(map.getModel())); + }); + + it("removeSelection when invalid model selected", function () { + var options = helper.createCustomMapOptions(); + + var map = new CustomMap(options); + map.setActiveSubmapId(-1); + + try { + map.removeSelection(); + assert.ok(false); + } catch (e) { + assert.ok(e.message.indexOf("Cannot find submap") >= 0); + } + }); + + describe("_openInfoWindowForIdentifiedElement", function () { + it("for AliasMarker", function () { + var map; + var alias, marker; + return ServerConnector.getProject().then(function (project) { + map = helper.createCustomMap(project); + return map.getModel().getAliasById(329171); + }).then(function (result) { + alias = result; + + var identifiedElement = new IdentifiedElement(alias); + identifiedElement.setIcon("empty.png"); + + marker = new AliasMarker({ + element: identifiedElement, + map: map + }); + + return marker.init(); + }).then(function () { + assert.equal(null, map.getAliasInfoWindowById(alias.getId())); + return map._openInfoWindowForIdentifiedElement(marker).then(function () { + assert.ok(map.getAliasInfoWindowById(alias.getId())); + }); + }); + + }); + it("for ReactionMarker", function () { + var map; + var reaction, marker; + return ServerConnector.getProject().then(function (project) { + map = helper.createCustomMap(project); + return map.getModel().getReactionById(153510); + }).then(function (result) { + reaction = result; + + marker = new ReactionMarker({ + element: new IdentifiedElement(reaction), + map: map + }); + return marker.init(); + }).then(function () { + assert.equal(null, map.getReactionInfoWindowById(reaction.getId())); + return map._openInfoWindowForIdentifiedElement(marker); + }).then(function () { + assert.ok(map.getReactionInfoWindowById(reaction.getId())); + }); + + }); + it("for PointMarker", function () { + + var mockObject = helper.createCustomMap(); + + mockObject.getOverlayDataForPoint = function () { + return Promise.resolve([]); + }; + + var point = new Point(2, 3.45); + var pointData = new PointData(point, mockObject.getId()); + + var pointMarker = new PointMarker({ + element: new IdentifiedElement(pointData), + map: mockObject + }); + + return pointMarker.init().then(function () { + assert.equal(null, mockObject.getPointInfoWindowById(pointData.getId())); + return mockObject._openInfoWindowForIdentifiedElement(pointMarker.getIdentifiedElement()); + }).then(function () { + assert.ok(mockObject.getPointInfoWindowById(pointData.getId())); + }); + }); + }); + + describe("init", function () { + it("invalid background overlay", function () { + var options = helper.createCustomMapOptions(); + ServerConnector.getSessionData(options.getProject()).setSelectedBackgroundOverlay("bla"); + var map = new CustomMap(options); + return map.init().then(function () { + assert.false("Error expected"); + }, function () { + map.destroy(); + }) + }); + + it("non-existing background overlay", function () { + var options = helper.createCustomMapOptions(); + ServerConnector.getSessionData(options.getProject()).setSelectedBackgroundOverlay(-1); + var map = new CustomMap(options); + return map.init().then(function () { + assert.ok(ServerConnector.getSessionData(options.getProject()).getSelectedBackgroundOverlay() > 0); + return map.destroy(); + }) + }); + + it("with session data overlays", function () { + var project = helper.createProject(); + var overlay1 = helper.createOverlay(); + overlay1.setInputDataAvailable(true); + project.addDataOverlay(overlay1); + + var options = helper.createCustomMapOptions(project); + ServerConnector.getSessionData(options.getProject()).setVisibleOverlays([overlay1.getId()]); + var map = new CustomMap(options); + return map.init().then(function () { + return map.getVisibleDataOverlays(); + }).then(function (overlays) { + assert.equal(1, overlays.length); + map.destroy(); + }) + }); + + }); + + describe("appendElementsPointingToSubmap", function () { + it("point to reaction", function () { + helper.setUrl("http://test/?id=complex_model_with_submaps"); + return ServerConnector.getProject().then(function (project) { + var map = helper.createCustomMap(project); + var oc = helper.createSearchDbOverlay(map); + + var reaction = new IdentifiedElement({id: 161955, modelId: 16729, type: "REACTION"}); + + return map.appendElementsPointingToSubmap([reaction], oc).then(function (elements) { + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + //alias pointing to reaction should have an icon + if (element.type === "ALIAS") { + assert.ok(element.getIcon() !== undefined); + } + } + }); + }); + }); + }); + describe("logo link", function () { + it("left logo click", function () { + var map = helper.createCustomMap(); + return map.getControl(ControlType.LOGO_2_IMG).onclick() + }); + it("right logo click", function () { + var map = helper.createCustomMap(); + return map.getControl(ControlType.LOGO_IMG).onclick() + }); + }); +}); diff --git a/frontend-js/src/test/js/map/canvas/GoogleMaps/GoogleMapsApiCanvas-test.js b/frontend-js/src/test/js/map/canvas/GoogleMaps/GoogleMapsApiCanvas-test.js index a95bd3d3adbf145d9ba74b55f38378bf4ac5eaaa..c91cf90576e5a09a1396eb0d8e05641f4c1e09f4 100644 --- a/frontend-js/src/test/js/map/canvas/GoogleMaps/GoogleMapsApiCanvas-test.js +++ b/frontend-js/src/test/js/map/canvas/GoogleMaps/GoogleMapsApiCanvas-test.js @@ -208,11 +208,41 @@ describe('GoogleMapsApiCanvas', function () { strokeColor: "#330000", strokeOpacity: 0.5, strokeWeight: 1.0, - id:"1", + id: "1", fillColor: "#00FF00", - bounds: new Bounds(new Point(0,0), new Point(2,2)) + bounds: new Bounds(new Point(0, 0), new Point(2, 2)) + }); + return google.maps.event.trigger(rectangle.getGoogleRectangles()[0], "click"); + }); + + it("set rectangle bounds", function () { + var canvas = new GoogleMapsApiCanvas(testDiv, testOptions); + var rectangle = canvas.createRectangle({ + fillOpacity: 0.7, + strokeColor: "#330000", + strokeOpacity: 0.5, + strokeWeight: 1.0, + id: "1", + fillColor: "#00FF00", + bounds: new Bounds(new Point(10, 10), new Point(20, 200)) + }); + rectangle.setBounds(new Bounds(new Point(100, 10), new Point(150, 200))); + var newBounds = rectangle.getBounds(); + assert.closeTo(newBounds.getTopLeft().distanceTo(new Point(100, 10)), 0, helper.EPSILON); + assert.closeTo(newBounds.getRightBottom().distanceTo(new Point(150, 200)), 0, helper.EPSILON); + }); + + it("create rectangle with gradient", function () { + var canvas = new GoogleMapsApiCanvas(testDiv, testOptions); + var rectangle = canvas.createRectangle({ + fillOpacity: 0.7, + strokeColor: "#330000", + strokeOpacity: 0.5, + strokeWeight: 1.0, + id: "1", + fillGradient: [{color: "#00FF00", amount: 1}, {color: "#00aa00", amount: 5}], + bounds: new Bounds(new Point(10, 10), new Point(20, 200)) }); - return google.maps.event.trigger(rectangle.getGoogleRectangle(), "click"); }); }); diff --git a/frontend-js/src/test/js/map/canvas/Point-test.js b/frontend-js/src/test/js/map/canvas/Point-test.js index bcc946c1c81c0000db065072aa7c56d2200088cb..505ec28a66ae3d41f3cabb2ef942dbdc5d027d64 100644 --- a/frontend-js/src/test/js/map/canvas/Point-test.js +++ b/frontend-js/src/test/js/map/canvas/Point-test.js @@ -28,5 +28,18 @@ describe('Point', function () { assert.equal(point.y, point2.y); }); }); + describe("distanceTo", function () { + it("the same", function () { + var point = new Point(12, 3); + assert.closeTo(point.distanceTo(point), 0, helper.EPSILON); + }); + it("different", function () { + var point = new Point(12, 3); + var point2 = new Point(15, 7); + assert.closeTo(point.distanceTo(point2), 5, helper.EPSILON); + assert.closeTo(point.distanceTo(new Point(15, 3)), 3, helper.EPSILON); + assert.closeTo(point.distanceTo(new Point(12, -1)), 4, helper.EPSILON); + }); + }); }); diff --git a/frontend-js/src/test/js/map/surface/AliasSurface-test.js b/frontend-js/src/test/js/map/surface/AliasSurface-test.js index 92ec4e60627ac61e2e6b09ae1a93b56ef40c7d48..4c98a6eb0db1934f67c8ddf5868744e2b0377a93 100644 --- a/frontend-js/src/test/js/map/surface/AliasSurface-test.js +++ b/frontend-js/src/test/js/map/surface/AliasSurface-test.js @@ -13,10 +13,9 @@ describe('AliasSurface', function () { it("default", function () { var map = helper.createCustomMap(); var alias = helper.createAlias(map); - var layoutAlias = helper.createLayoutAlias(alias); var result = new AliasSurface({ - overlayAlias: layoutAlias, + overlayData: [helper.createLayoutAlias(alias)], alias: alias, map: map, startX: 1, @@ -30,10 +29,9 @@ describe('AliasSurface', function () { it("no bounds", function () { var map = helper.createCustomMap(); var alias = helper.createAlias(map); - var layoutAlias = helper.createLayoutAlias(alias); var result = new AliasSurface({ - overlayAlias: layoutAlias, + overlayData: [helper.createLayoutAlias(alias)], alias: alias, map: map }); @@ -55,6 +53,7 @@ describe('AliasSurface', function () { alias = result; surface = new AliasSurface({ alias: result, + overlayData: [helper.createLayoutAlias(alias)], map: map }); return surface.init(); @@ -71,7 +70,7 @@ describe('AliasSurface', function () { var map = helper.createCustomMap(); var alias = helper.createAlias(map); var surface = new AliasSurface({ - overlayAlias: helper.createLayoutAlias(alias), + overlayData: [helper.createLayoutAlias(alias)], alias: alias, map: map, startX: 1, @@ -97,6 +96,7 @@ describe('AliasSurface', function () { alias = result; surface = new AliasSurface({ alias: result, + overlayData: [helper.createLayoutAlias(result)], map: map, onClick: function () { clicked = true; diff --git a/frontend-js/src/test/js/map/window/AliasInfoWindow-test.js b/frontend-js/src/test/js/map/window/AliasInfoWindow-test.js index 627d901f4eb3c93642f97cfe0c1cacdfe60fa9b0..85c8f1ca153eba39ac234e5ed51849a6f58734da 100644 --- a/frontend-js/src/test/js/map/window/AliasInfoWindow-test.js +++ b/frontend-js/src/test/js/map/window/AliasInfoWindow-test.js @@ -246,9 +246,9 @@ describe('AliasInfoWindow', function () { }); return win.init(); }).then(function () { - win.layoutAliases = [layoutAlias]; - win.layoutNames = ["xxx"]; - return win.createGenomicDiv(); + var overlay = helper.createOverlay(); + overlay.addAlias(layoutAlias); + return win.createGenomicDiv({overlays: [overlay]}); }).then(function (div) { assert.ok(div); assert.ok(div.innerHTML.indexOf("No reference genome data available on minerva platform") === -1); @@ -257,41 +257,6 @@ describe('AliasInfoWindow', function () { }); - it("on submap map", function () { - helper.setUrl("http://test/?id=complex_model_with_submaps"); - - var map, submap, overlay, win, alias; - - return ServerConnector.getProject().then(function (project) { - map = helper.createCustomMap(project); - submap = map.getSubmapById(16731); - overlay = new DataOverlay(18077, "xxx"); - overlay.setInitialized(true); - return map.openSubmap(submap.getId()); - }).then(function () { - return submap.getModel().getAliasById(345337); - }).then(function (data) { - alias = data; - win = new AliasInfoWindow({ - alias: alias, - map: submap, - marker: helper.createMarker({element: alias, map: submap}) - }); - return win.init(); - }).then(function () { - var layoutAlias = helper.createLayoutAlias(alias); - layoutAlias.setType(LayoutAlias.GENETIC_VARIANT); - win.layoutAliases = [layoutAlias]; - win.layoutNames = ["xxx"]; - return win.createGenomicDiv(); - }).then(function (div) { - assert.ok(div); - win.destroy(); - return map.destroy(); - }); - - }); - it("with no genetic data", function () { var map; @@ -312,8 +277,8 @@ describe('AliasInfoWindow', function () { }); return win.init(); }).then(function () { - win.layoutAliases = [undefined]; - return win.createGenomicDiv(); + var overlays = [helper.createOverlay()]; + return win.createGenomicDiv({overlays: overlays}); }).then(function (div) { assert.ok(div); assert.ok(div.innerHTML.indexOf("No reference genome data available on minerva platform") === -1); @@ -350,8 +315,9 @@ describe('AliasInfoWindow', function () { }); return win.init(); }).then(function () { - win.layoutAliases = [layoutAlias]; - return win.createGenomicDiv(); + var overlay = helper.createOverlay(); + overlay.addAlias(layoutAlias); + return win.createGenomicDiv({overlays: [overlay]}); }).then(function (div) { assert.ok(div); assert.ok(div.innerHTML.indexOf("No reference genome data available on minerva platform") >= -1); @@ -375,28 +341,70 @@ describe('AliasInfoWindow', function () { assert.ok(functions.isDomElement(aliasWindow.createWaitingContentDiv())); }); - it("createChartDiv ", function () { - var map, ie, aliasWindow; - return ServerConnector.getProject().then(function (project) { - map = helper.createCustomMap(project); - ie = new IdentifiedElement({ - id: 329170, - modelId: map.getId(), - type: "ALIAS" + describe("createChartDiv ", function () { + it("on submap map", function () { + helper.setUrl("http://test/?id=complex_model_with_submaps"); + + var map, submap, overlay, win, aliasOnSubmap, alias; + + return ServerConnector.getProject().then(function (project) { + map = helper.createCustomMap(project); + submap = map.getSubmapById(16731); + overlay = new DataOverlay(18077, "xxx"); + overlay.setInitialized(true); + return map.openSubmap(submap.getId()); + }).then(function () { + return map.getModel().getAliasById(345339); + }).then(function (data) { + alias = data; + return submap.getModel().getAliasById(345337); + }).then(function (data) { + aliasOnSubmap = data; + win = new AliasInfoWindow({ + alias: alias, + map: map, + marker: helper.createMarker({element: alias, map: map}) + }); + return win.init(); + }).then(function () { + var layoutAlias = helper.createLayoutAlias(aliasOnSubmap); + layoutAlias.setType(LayoutAlias.GENERIC); + var overlay = helper.createOverlay(); + overlay.addAlias(layoutAlias); + return win.createChartDiv({overlays: [overlay]}); + }).then(function (div) { + assert.ok(div); + win.destroy(); + return map.destroy(); }); - return map.getModel().getByIdentifiedElement(ie, true); - }).then(function (alias) { - aliasWindow = new AliasInfoWindow({ - alias: alias, - map: map, - marker: helper.createMarker({element: alias, map: map}) + }); + + it("default ", function () { + var map, ie, aliasWindow; + return ServerConnector.getProject().then(function (project) { + map = helper.createCustomMap(project); + ie = new IdentifiedElement({ + id: 329170, + modelId: map.getId(), + type: "ALIAS" + }); + + return map.getModel().getByIdentifiedElement(ie, true); + }).then(function (alias) { + aliasWindow = new AliasInfoWindow({ + alias: alias, + map: map, + marker: helper.createMarker({element: alias, map: map}) + }); + var overlay = helper.createOverlay(); + overlay.addAlias(helper.createLayoutAlias(alias, LayoutAlias.GENERIC)); + var overlays = [overlay, helper.createOverlay()]; + + return aliasWindow.createChartDiv({overlays: overlays}); + }).then(function (div) { + assert.ok(div); }); - aliasWindow.layoutAliases = [helper.createLayoutAlias(alias), null]; - aliasWindow.layoutNames = ["x", "y"]; - return aliasWindow.createChartDiv(); - }).then(function (div) { - assert.ok(div); }); }); diff --git a/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345325&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345325&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345325&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345325&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345330&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345330&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345330&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345330&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345330,345331,345337&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345330,345331,345337&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345330,345331,345337&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345330,345331,345337&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345331&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345331&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345331&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345331&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345334&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345334&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345334&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345334&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345337&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345337&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345337&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345337&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345339&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345339&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId&id=345339&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/complex_model_with_submaps/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=345339&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/drug_target_sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=436152&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/drug_target_sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=436152&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/drug_target_sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=436152&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/drug_target_sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=436152&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=-1&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=-1&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=-1&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=-1&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329157&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329157&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329157&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329157&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329159&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329159&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329159&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329159&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329163&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329163&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329163&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329163&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329167&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329167&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329167&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329167&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329168,329173&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329168,329173&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329168,329173&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329168,329173&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329170&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329170&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329170&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329170&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329171&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329171&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329171&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329171&token=MOCK_TOKEN_ID& diff --git a/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329173&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329173&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId&id=329173&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/sample/models/all/bioEntities/elements/columns=id,bounds,modelId,linkedSubmodel&id=329173&token=MOCK_TOKEN_ID&