From 8ed7a9041ea134a9f4eea1c37d1ca0740ae83641 Mon Sep 17 00:00:00 2001 From: Anthony Garcia Date: Fri, 27 Sep 2013 11:19:58 +0200 Subject: [PATCH] add skeleton for senslabmap plugin --- plugins/senslabmap/static/css/senslabmap.css | 19 +- plugins/senslabmap/static/js/senslabmap.js | 132 ++--- plugins/senslabmap/static/js/viewer3D.js | 521 ++++++++++--------- plugins/senslabmap/templates/senslabmap.html | 26 +- portal/demo_sliceview.py | 8 + 5 files changed, 365 insertions(+), 341 deletions(-) diff --git a/plugins/senslabmap/static/css/senslabmap.css b/plugins/senslabmap/static/css/senslabmap.css index cfd2d941..064b4d3e 100644 --- a/plugins/senslabmap/static/css/senslabmap.css +++ b/plugins/senslabmap/static/css/senslabmap.css @@ -1,11 +1,14 @@ -.senslab-map { - width: 800px; - height: 500px; - height: 100%; +.senslabmap { + margin: 10px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + line-height: 18px; + color: #333333; + background-color: #ffffff; } #div3d { - width: 100%; - height: 500px; - background-color: #202020; -} + height: 500px; + background-color: #202020; + z-index:-1 +} \ No newline at end of file diff --git a/plugins/senslabmap/static/js/senslabmap.js b/plugins/senslabmap/static/js/senslabmap.js index 8075be9c..68e2189c 100644 --- a/plugins/senslabmap/static/js/senslabmap.js +++ b/plugins/senslabmap/static/js/senslabmap.js @@ -1,80 +1,52 @@ -/** - * Description: SensLab display of 3D-geolocated data - * Copyright (c) 2012 UPMC Sorbonne Universite - INRIA - * License: GPLv3 - */ - -// xxx TODO -- this plugin has never been tested -// update_map looks suspiciously empty... -// in addition it could use a bit of cleaning like what was done for the first plugins -// especially wrt using 'instance' and 'data' in such a confusing way - -(function( $ ){ - - $.fn.SensLabMap = function( method ) { - /* Method calling logic */ - if ( methods[method] ) { - return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); - } else if ( typeof method === 'object' || ! method ) { - return methods.init.apply( this, arguments ); - } else { - $.error( 'Method ' + method + ' does not exist on $.SensLabMap' ); - } - }; - - var methods = { - init : function( options ) { - return this.each(function(){ - var $this = $(this), - data = $this.data('SensLabMap'), SensLabMap = $('
', { text : $this.attr('title') }); - // If the plugin hasn't been initialized yet - if ( ! data ) { - /* Plugin initialization */ - //google.load('maps', '3', { other_params: 'sensor=false' }); - //google.setOnLoadCallback(initialize); - init(); - /* End of plugin initialization */ - $(this).data('SensLabMap', { - plugin_uuid: options.plugin_uuid, - query_uuid: options.query_uuid, - target : $this, - SensLabMap : SensLabMap - }); - /* Subscribe to query updates */ - $.subscribe('/results/' + options.query_uuid + '/changed', {instance: $this}, update_map); - } - }); - }, - destroy : function( ) { - return this.each(function(){ - var $this = $(this), data = $this.data('SensLabMap'); - $(window).unbind('SensLabMap'); - data.SensLabMap.remove(); - $this.removeData('SensLabMap'); - }); - }, -/* - reposition : function( ) { // ... }, - show : function( ) { // ... }, - hide : function( ) { // ... }, -*/ - update : function( content ) { - // should be made a private function - set3dsize() - }, - }; - - /* Private methods */ - function update_map(e, rows) { - var $plugindiv = e.data.instance; - $plugindiv.closest('.need-spin').spin(false); - - if(rows) { - /* TODO rendering */ - } else { - alert('error'); - } - - } - -})( jQuery ); +(function($){ + var SensLabMap = Plugin.extend({ + init: function(options, element) { + this._super(options, element); + + /* Member variables */ + // query status + this.received_all = false; + this.received_set = false; + this.in_set_buffer = Array(); + + this.el().on('show', this, this.on_show); + + var query = manifold.query_store.find_analyzed_query(options.query_uuid); + this.method = query.object; + + var keys = manifold.metadata.get_key(this.method); + this.key = (keys && keys.length == 1) ? keys[0] : null; + + /* Setup query and record handlers */ + this.listen_query(options.query_uuid); + this.listen_query(options.query_uuid, 'all'); + + /* GUI setup and event binding */ + this.initialize_map(); + }, + + initialize_map: function() { + // TODO: this is static, retrieve directly nodes + nodes = nodes_gre; + init(); + parseNodebox(); + }, + + on_show: function(e) { + // TODO + }, + + on_filter_added: function(filter) { + console.log(filter); + }, + + on_new_record: function(record) { + console.log(record); + }, + + on_record_received: function(record) { + console.log(record); + }, + }); + $.plugin('SensLabMap', SensLabMap); +})(jQuery); diff --git a/plugins/senslabmap/static/js/viewer3D.js b/plugins/senslabmap/static/js/viewer3D.js index cf70e812..1536921c 100644 --- a/plugins/senslabmap/static/js/viewer3D.js +++ b/plugins/senslabmap/static/js/viewer3D.js @@ -1,14 +1,12 @@ - -// Various global variables -var mouseX = 0, mouseY = 0, - camera, scene, renderer, projector; +// Various global variables +var mouseX = 0, mouseY = 0,camera, scene, renderer, projector; var sTestEventType = 'mousedown'; //var window3DWidth = window.innerWidth * 0.8; //var window3DHeight=window.innerHeight*0.75; var window3DWidth, window3DHeight; var offX, offY; // Camera parameters -phi = -100, theta = 0, distance = 150; +phi = -100, theta = 0, distance = 130; var rcount = 0; // Text display var info, nodelist, help; @@ -21,322 +19,341 @@ var selectedNodes = []; var div3d, nodebox, infobox; -function init() { - var particles, particle; - - // jordan : modifier document.getElementById - div3d = jQuery('#div3d'); - nodebox = jQuery('#nodebox'); - infobox = jQuery('#infobox'); - titlebox = jQuery('#titlebox'); - // offset also - var offset = div3d.offset(); - offY = offset.top; - offX = offset.left; - - titlebox.innerHTML = 'Grenoble Site ' + nodes_gre.length + " nodes"; - infobox.innerHTML = 'Node info : '; - - nodebox.value = ""; - - camera = new THREE.PerspectiveCamera(75, window3DWidth / window3DHeight, 1, 10000); +var nodes = []; - scene = new THREE.Scene(); - - renderer = new THREE.CanvasRenderer(); - - // jordan XXX div3d.appendChild(renderer.domElement); - div3d.append(renderer.domElement); - - window.addEventListener('resize', set3dsize, false); - scene.add(camera); - set3dsize(); +function init() { + var particles, particle; + + div3d = JQuery('#div3d'); + nodebox = JQuery('#nodebox'); + infobox = JQuery('#infobox'); + titlebox = JQuery('#titlebox'); + + var offset = div3d.offset; + offY = div3d.top; + offX = div3d.left; + + //titlebox.innerHTML = 'Grenoble Site ' + nodes.length + " nodes"; + infobox.innerHTML = 'Node info : '; + + nodebox.value = ""; + + camera = new THREE.PerspectiveCamera(75, window3DWidth / window3DHeight, 1, 10000); + + scene = new THREE.Scene(); + + renderer = new THREE.CanvasRenderer(); + + div3d.append(renderer.domElement); + + window.addEventListener('resize', set3dsize, false); + scene.add(camera); + set3dsize(); + + + var PI2 = Math.PI * 2; + var geometry = new THREE.Geometry(); + + // let's find the center of the nodes + xmin = ymin = zmin = 0; + xmax = ymax = zmax = 0; + + for (var i = 0; i < nodes.length; i++) { + if (nodes[i][1] > xmax) xmax = nodes[i][1]; + if (nodes[i][1] < xmin) xmin = nodes[i][1]; + if (nodes[i][2] > ymax) ymax = nodes[i][2]; + if (nodes[i][2] < ymin) ymin = nodes[i][2]; + if (nodes[i][3] > zmax) zmax = nodes[i][3]; + if (nodes[i][3] < zmin) zmin = nodes[i][3]; + } + + xcenter = (xmax + xmin) / 2; + ycenter = (ymax + ymin) / 2; + zcenter = (zmax + zmin) / 2; + + // display nodes as TREE particles + for (var i = 0; i < nodes.length; i++) { + material = new THREE.ParticleCanvasMaterial({ + color: 0xffffff, + program: function (context) { + context.beginPath(); + context.arc(0, 0, 1, 0, PI2, true); + context.closePath(); + context.fill(); + } + }); + particle = new THREE.Particle(material); + particle.name = nodes[i][0]; + particle.position.x = nodes[i][1] - xcenter; + particle.position.y = nodes[i][2] - ycenter; + particle.position.z = nodes[i][3] - zcenter; + particle.uid = nodes[i][4]; + particle.state = nodes[i][5]; + particle.position.multiplyScalar(10); + particle.scale.x = particle.scale.y = 1; + scene.add(particle); + v = new THREE.Vertex(particle.position); + geometry.vertices.push(v); + objects.push(particle) - - var PI2 = Math.PI * 2; - var geometry = new THREE.Geometry(); - - // let's find the center of the nodes - xmin = ymin = zmin = 0; - xmax = ymax = zmax = 0; - - for (var i = 0; i < nodes_gre.length; i++) { - if (nodes_gre[i][1] > xmax) xmax = nodes_gre[i][1]; - if (nodes_gre[i][1] < xmin) xmin = nodes_gre[i][1]; - if (nodes_gre[i][2] > ymax) ymax = nodes_gre[i][2]; - if (nodes_gre[i][2] < ymin) ymin = nodes_gre[i][2]; - if (nodes_gre[i][3] > zmax) zmax = nodes_gre[i][3]; - if (nodes_gre[i][3] < zmin) zmin = nodes_gre[i][3]; - } - - xcenter = (xmax + xmin) / 2; - ycenter = (ymax + ymin) / 2; - zcenter = (zmax + zmin) / 2; - - // display nodes as TREE particles - for (var i = 0; i < nodes_gre.length; i++) { - material = new THREE.ParticleCanvasMaterial({ - color: 0xffffff, - program: function (context) { - context.beginPath(); - context.arc(0, 0, 1, 0, PI2, true); - context.closePath(); - context.fill(); - } - }); - particle = new THREE.Particle(material); - particle.name = nodes_gre[i][0]; - particle.position.x = nodes_gre[i][1] - xcenter; - particle.position.y = nodes_gre[i][2] - ycenter; - particle.position.z = nodes_gre[i][3] - zcenter; - particle.position.multiplyScalar(10); - particle.scale.x = particle.scale.y = 1; - scene.add(particle); - v = new THREE.Vertex(particle.position); - geometry.vertices.push(v); - objects.push(particle) - } - - debugaxis(10); - // a projector is needed to find which node is under the mouse - projector = new THREE.Projector(); - - nodebox.onkeyup = parseNodebox; - // set mouse event handlers // TODO jordan - document.onmousedown = OnMouseDown; - document.onmouseup = OnMouseUp; - document.onmousemove = displayNodeInfo; - if (window.addEventListener) + } + + debugaxis(10); + // a projector is needed to find which node is under the mouse + projector = new THREE.Projector(); + + nodebox.onkeyup = parseNodebox; + // set mouse event handlers + div3d.onmousedown = OnMouseDown; + div3d.onmouseup = OnMouseUp; + div3d.onmousemove = displayNodeInfo; + if (div3d.addEventListener) /** DOMMouseScroll is for mozilla. */ - window.addEventListener('DOMMouseScroll', wheel, false); - /** IE/Opera. */ - window.onmousewheel = document.onmousewheel = wheel; - myrender(); + div3d.addEventListener('DOMMouseScroll', wheel, false); + /** IE/Opera. */ + div3d.onmousewheel = div3d.onmousewheel = wheel; + myrender(); } function set3dsize() { - // jordan - var offset = div3d.offset(); - offY = offset.top; - offX = offset.left; - window3DWidth = div3d.width(); - window3DHeight = div3d.height(); - renderer.setSize(window3DWidth, window3DHeight); - - camera.aspect = window3DWidth / window3DHeight; - camera.updateProjectionMatrix(); - - myrender(); + var offset = div3d.offset; + offY = offset.top; + offX = offset.left; + window3DWidth = offset.width; + window3DHeight = offset.height; + renderer.setSize(window3DWidth, window3DHeight); + + camera.aspect = window3DWidth / window3DHeight; + camera.updateProjectionMatrix(); + + myrender(); } function sortfunction(a, b) { - return (a - b) //causes an array to be sorted numerically and ascending + return (a - b) //causes an array to be sorted numerically and ascending } // factorize the expanded list in selectedNode to produce dash intervals // 1,2,3,5,9 -> 1-3,5,9 function factorize() { - var fact = []; - var previous = 0; - var intervalStart = 0; - selectedNodes.sort(sortfunction); - for (j = 0; j < selectedNodes.length; j++) { - if (intervalStart) { - // we are in an interval - if (selectedNodes[j] == previous + 1) { - // interval grows - previous += 1; - } else { - // end of interval - fact.push(intervalStart + "-" + previous); - intervalStart = 0; - previous = selectedNodes[j]; - } - } else { - // we are not in an interval - if (selectedNodes[j] == previous + 1) { - // let's begin an interval - intervalStart = previous; - previous += 1; - } else { - if (previous) fact.push(previous); - previous = selectedNodes[j]; - } - } - } // for end - // at the end of the loop, two cases - // we were still in an interval, then add it to the result - // we were not in an interval, then add the last selectednode (previous) + var fact = []; + var previous = 0; + var intervalStart = 0; + selectedNodes.sort(sortfunction); + for (j = 0; j < selectedNodes.length; j++) { if (intervalStart) { + // we are in an interval + if (selectedNodes[j] == previous + 1) { + // interval grows + previous += 1; + } else { + // end of interval fact.push(intervalStart + "-" + previous); + intervalStart = 0; + previous = selectedNodes[j]; + } } else { + // we are not in an interval + if (selectedNodes[j] == previous + 1) { + // let's begin an interval + intervalStart = previous; + previous += 1; + } else { if (previous) fact.push(previous); + previous = selectedNodes[j]; + } } - return fact; + } // for end + // at the end of the loop, two cases + // we were still in an interval, then add it to the result + // we were not in an interval, then add the last selectednode (previous) + if (intervalStart) { + fact.push(intervalStart + "-" + previous); + } else { + if (previous) fact.push(previous); + } + return fact; } // expand a list of nodes containing dash intervals // 1-3,5,9 -> 1,2,3,5,9 function expand(factExp) { - exp = []; - for (i = 0; i < factExp.length; i++) { - dashExpression = factExp[i].split("-"); - if (dashExpression.length == 2) { - for (j = parseInt(dashExpression[0]); j < (parseInt(dashExpression[1]) + 1); j++) - exp.push(j); - } else exp.push(parseInt(factExp[i])); - } - exp.sort(sortfunction); - for (var i = 1; i < exp.length; i++) { if (exp[i] == exp[i - 1]) { exp.splice(i--, 1); } } - return exp; + exp = []; + for (i = 0; i < factExp.length; i++) { + dashExpression = factExp[i].split("-"); + if (dashExpression.length == 2) { + for (j = parseInt(dashExpression[0]); j < (parseInt(dashExpression[1]) + 1); j++) + exp.push(j); + } else exp.push(parseInt(factExp[i])); + } + exp.sort(sortfunction); + for (var i = 1; i < exp.length; i++) { if (exp[i] == exp[i - 1]) { exp.splice(i--, 1); } } + return exp; } function parseNodebox() { - input = nodebox.value; - selectedNodes = expand(input.split(",")); - myrender(); + input = nodebox.value; + selectedNodes = expand(input.split(",")); + myrender(); } function debugaxis(axisLength) { - //Shorten the vertex function - function v(x, y, z) { - return new THREE.Vertex(new THREE.Vector3(x, y, z)); - } - - //Create axis (point1, point2, colour) - function createAxis(p1, p2, color) { - var line, lineGeometry = new THREE.Geometry(), - lineMat = new THREE.LineBasicMaterial({ color: color, lineWidth: 2 }); - lineGeometry.vertices.push(p1, p2); - line = new THREE.Line(lineGeometry, lineMat); - scene.add(line); - } - - createAxis(v(0, 0, 0), v(axisLength, 0, 0), 0xFF0000); - createAxis(v(0, 0, 0), v(0, axisLength, 0), 0x00FF00); - createAxis(v(0, 0, 0), v(0, 0, axisLength), 0x0000FF); + //Shorten the vertex function + function v(x, y, z) { + return new THREE.Vertex(new THREE.Vector3(x, y, z)); + } + + //Create axis (point1, point2, colour) + function createAxis(p1, p2, color) { + var line, lineGeometry = new THREE.Geometry(), + lineMat = new THREE.LineBasicMaterial({ color: color, lineWidth: 2 }); + lineGeometry.vertices.push(p1, p2); + line = new THREE.Line(lineGeometry, lineMat); + scene.add(line); + } + + createAxis(v(0, 0, 0), v(axisLength, 0, 0), 0xFF0000); + createAxis(v(0, 0, 0), v(0, axisLength, 0), 0x00FF00); + createAxis(v(0, 0, 0), v(0, 0, axisLength), 0x0000FF); }; // set the camera position according two angles theta and phi and the distance // and display the scene function myrender() { - //infobox.innerHTML = " Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z - // + " - " + theta + "," + phi + ","+ distance; - //infobox.innerHTML = selectedNodes; - camera.position.x = distance * Math.sin(theta * Math.PI / 360) * Math.cos(phi * Math.PI / 360); - camera.position.y = distance * Math.sin(this.phi * Math.PI / 360); - camera.position.z = distance * Math.cos(this.theta * Math.PI / 360) * Math.cos(this.phi * Math.PI / 360); - camera.lookAt(scene.position); - camera.updateMatrix(); - - for (i = 0; i < objects.length; i++) - if (selectedNodes.indexOf(objects[i].name) != -1) objects[i].material.color.setHex(0xff0000); - else objects[i].material.color.setHex(0xffffff); - renderer.render(scene, camera); + //infobox.innerHTML = " Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z + // + " - " + theta + "," + phi + ","+ distance; + //infobox.innerHTML = selectedNodes; + camera.position.x = distance * Math.sin(theta * Math.PI / 360) * Math.cos(phi * Math.PI / 360); + camera.position.y = distance * Math.sin(this.phi * Math.PI / 360); + camera.position.z = distance * Math.cos(this.theta * Math.PI / 360) * Math.cos(this.phi * Math.PI / 360); + camera.lookAt(scene.position); + camera.updateMatrix(); + + for (i = 0; i < objects.length; i++) { + + if (selectedNodes.indexOf(objects[i].name) != -1) { + objects[i].material.color.setHex(0x0099CC); + } + else { + if(objects[i].state == "Busy") { + objects[i].material.color.setHex(0x9943BE); + } + else if(objects[i].state == "Alive") { + objects[i].material.color.setHex(0x7FFF00); + } + else { + objects[i].material.color.setHex(0xFF3030); + } } -// rigthbutton is used for rotations -function onDocumentMouseMoveRot(event) { - NewmouseX = event.clientX; - NewmouseY = event.clientY; - DeltaX = NewmouseX - mouseX; - DeltaY = NewmouseY - mouseY; - mouseX = NewmouseX; - mouseY = NewmouseY; +} +renderer.render(scene, camera); +} - theta -= DeltaX; - phi += DeltaY; - if (phi > 180) phi = 180; - if (phi < -180) phi = -180; - myrender(); +// rigthbutton is used for rotations +function onDocumentMouseMoveRot(event) { + NewmouseX = event.clientX; + NewmouseY = event.clientY; + DeltaX = NewmouseX - mouseX; + DeltaY = NewmouseY - mouseY; + + mouseX = NewmouseX; + mouseY = NewmouseY; + + theta -= DeltaX; + phi += DeltaY; + if (phi > 180) phi = 180; + if (phi < -180) phi = -180; + myrender(); } // mousewheel is used for zoom function Zoom(delta) { - distance += delta * 5; - myrender(); + distance += delta * 5; + myrender(); } // return the graphical node under the mouse function findNodeUnderMouse(event) { - var vector = new THREE.Vector3(((event.clientX - offX) / window3DWidth) * 2 - 1, -((event.clientY - offY) / window3DHeight) * 2 + 1, 0.5); - projector.unprojectVector(vector, camera); - var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize()); - var intersects = ray.intersectObjects(objects); - if (intersects.length > 0) { - return intersects[0]; - } else return null; + var vector = new THREE.Vector3(((event.clientX - offX) / window3DWidth) * 2 - 1, -((event.clientY - offY) / window3DHeight) * 2 + 1, 0.5); + projector.unprojectVector(vector, camera); + var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize()); + var intersects = ray.intersectObjects(objects); + if (intersects.length > 0) { + return intersects[0]; + } else return null; } // display some info of the node under the mouse function displayNodeInfo(e) { - obj = findNodeUnderMouse(e); - if (obj) infobox.innerHTML = 'Node info : number ' + obj.object.name + " with id " + nodes_gre[obj.object.id][4]; - // else infobox.innerHTML = e.clientX + "," + e.clientY + " - " + offX + "," + offY; + obj = findNodeUnderMouse(e); + + if (obj) infobox.innerHTML = 'Node info : number ' + obj.object.name + " with id " + obj.object.uid; + // else infobox.innerHTML = e.clientX + "," + e.clientY + " - " + offX + "," + offY; } // select/unselect nodes function toggleNode(obj) { - nodeId = obj.object.name; - i = selectedNodes.indexOf(nodeId); - if (i == -1) selectedNodes.push(nodeId); - else selectedNodes.splice(i, 1); - nodebox.value = factorize().join(","); - myrender(); + nodeId = obj.object.name; + i = selectedNodes.indexOf(nodeId); + if (i == -1) selectedNodes.push(nodeId); + else selectedNodes.splice(i, 1); + nodebox.value = factorize().join(","); + myrender(); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Mouse handling functions // function OnMouseDown(e) { - var clickType = 'LEFT'; - if (e.type != sTestEventType) return true + var clickType = 'LEFT'; + if (e.type != sTestEventType) return true if (e.which) { - if (e.which == 3) clickType = 'RIGHT'; - if (e.which == 2) clickType = 'MIDDLE'; - //infobox.innerHTML = clickType + " - Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z; + if (e.which == 3) clickType = 'RIGHT'; + if (e.which == 2) clickType = 'MIDDLE'; + //infobox.innerHTML = clickType + " - Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z; } mouseX = e.clientX; - mouseY = e.clientY; - if (clickType == 'RIGHT') { - document.onmousemove = onDocumentMouseMoveRot; - } - if (clickType == 'LEFT') { - obj = findNodeUnderMouse(e); - if (obj != null) toggleNode(obj); - } + mouseY = e.clientY; + if (clickType == 'RIGHT') { + document.onmousemove = onDocumentMouseMoveRot; + } + if (clickType == 'LEFT') { + obj = findNodeUnderMouse(e); + if (obj != null) toggleNode(obj); + } } function OnMouseUp(e) { - document.onmousemove = displayNodeInfo; + document.onmousemove = displayNodeInfo; } // This function was taken here : http://www.adomas.org/javascript-mouse-wheel/ // Event handler for mouse wheel event. function wheel(event) { - var delta = 0; - if (!event) /* For IE. */ - event = window.event; - if (event.wheelDelta) { /* IE/Opera. */ - delta = event.wheelDelta / 120; - } else if (event.detail) { /** Mozilla case. */ - /** In Mozilla, sign of delta is different than in IE. - * Also, delta is multiple of 3. - */ - delta = -event.detail / 3; - } - /** If delta is nonzero, handle it. - * Basically, delta is now positive if wheel was scrolled up, - * and negative, if wheel was scrolled down. - */ - if (delta) - Zoom(delta); - /** Prevent default actions caused by mouse wheel. - * That might be ugly, but we handle scrolls somehow - * anyway, so don't bother here.. - */ - if (event.preventDefault) - event.preventDefault(); - event.returnValue = false; -} + var delta = 0; + if (!event) /* For IE. */ + event = window.event; + if (event.wheelDelta) { /* IE/Opera. */ + delta = event.wheelDelta / 120; + } else if (event.detail) { /** Mozilla case. */ + /** In Mozilla, sign of delta is different than in IE. + * Also, delta is multiple of 3. + */ + delta = -event.detail / 3; + } + /** If delta is nonzero, handle it. + * Basically, delta is now positive if wheel was scrolled up, + * and negative, if wheel was scrolled down. + */ + if (delta) + Zoom(delta); + /** Prevent default actions caused by mouse wheel. + * That might be ugly, but we handle scrolls somehow + * anyway, so don't bother here.. + */ + if (event.preventDefault) + event.preventDefault(); + event.returnValue = false; +} diff --git a/plugins/senslabmap/templates/senslabmap.html b/plugins/senslabmap/templates/senslabmap.html index c1c65996..639385d0 100644 --- a/plugins/senslabmap/templates/senslabmap.html +++ b/plugins/senslabmap/templates/senslabmap.html @@ -1 +1,25 @@ -
+
+
+
+
+ Selected Nodes + +
+
+
+
+ Alive - + Down - + Selected - + Busy +
+
+
+ +
\ No newline at end of file diff --git a/portal/demo_sliceview.py b/portal/demo_sliceview.py index a678e33f..28b24a61 100644 --- a/portal/demo_sliceview.py +++ b/portal/demo_sliceview.py @@ -156,6 +156,14 @@ class SliceView (LoginRequiredAutoLogoutView): }, )) + tab_resource_plugins.insert(SensLabMap( + page = page, + title = 'SensLab Map', + domid = 'senslabmap', + query = sq_resource, # query slice resources + query_all = query_resource_all # query all resources + )) + tab_resource_plugins.insert(GoogleMap( page = page, title = 'Geographic view', -- 2.43.0