Add modif senslabmap
[myslice.git] / plugins / senslabmap / static / js / viewer3D.js
index cf70e81..33ae659 100644 (file)
@@ -1,17 +1,8 @@
-\r
-// Various global variables\r
-var mouseX = 0, mouseY = 0,\r
-                       camera, scene, renderer, projector;\r
-var sTestEventType = 'mousedown';\r
-//var window3DWidth = window.innerWidth * 0.8;\r
-//var window3DHeight=window.innerHeight*0.75;\r
-var window3DWidth, window3DHeight;\r
-var offX, offY;\r
+// Various global variables\r
+var mouseX = 0, mouseY = 0, camera, scene, renderer, projector;\r
+\r
 // Camera parameters\r
-phi = -100, theta = 0, distance = 150;\r
-var rcount = 0;\r
-// Text display\r
-var info, nodelist, help;\r
+var phi = -100, theta = 0, distance = 130;\r
 \r
 // graphical nodes\r
 var objects = [];\r
@@ -21,322 +12,331 @@ var selectedNodes = [];
 \r
 var div3d, nodebox, infobox;\r
 \r
-function init() {\r
-    var particles, particle;\r
-\r
-    // jordan : modifier document.getElementById\r
-    div3d = jQuery('#div3d');\r
-    nodebox = jQuery('#nodebox');\r
-    infobox = jQuery('#infobox');\r
-    titlebox = jQuery('#titlebox');\r
-    // offset also\r
-    var offset = div3d.offset();\r
-    offY = offset.top;\r
-    offX = offset.left;\r
-\r
-    titlebox.innerHTML = 'Grenoble Site ' + nodes_gre.length + " nodes";\r
-    infobox.innerHTML = 'Node info : ';\r
-\r
-    nodebox.value = "";\r
-\r
-    camera = new THREE.PerspectiveCamera(75, window3DWidth / window3DHeight, 1, 10000);\r
-\r
-    scene = new THREE.Scene();\r
+function onResize() {\r
+  renderer.setSize(div3d.offsetWidth, div3d.offsetHeight);\r
+  camera.aspect = div3d.offsetWidth / div3d.offsetHeight;\r
+  camera.updateProjectionMatrix();\r
+  myrender();\r
+}\r
 \r
-    renderer = new THREE.CanvasRenderer();\r
+function getCenter(nodes) {\r
+  var xmin = 0, ymin = 0, zmin = 0;\r
+  var xmax = 0, ymax = 0, zmax = 0;\r
+  \r
+  for (var i = 0; i < nodes.length; i++) {\r
+    if (nodes[i][1] > xmax) xmax = nodes[i][1];\r
+    if (nodes[i][1] < xmin) xmin = nodes[i][1];\r
+    if (nodes[i][2] > ymax) ymax = nodes[i][2];\r
+    if (nodes[i][2] < ymin) ymin = nodes[i][2];\r
+    if (nodes[i][3] > zmax) zmax = nodes[i][3];\r
+    if (nodes[i][3] < zmin) zmin = nodes[i][3];\r
+  }\r
+  return {x: (xmax + xmin) / 2, y: (ymax + ymin) / 2, z: (zmax + zmin) / 2};\r
+}\r
 \r
-    // jordan XXX div3d.appendChild(renderer.domElement);\r
-    div3d.append(renderer.domElement);\r
+function debugaxis(axisLength) {\r
+  var v = function(x, y, z) {\r
+    return new THREE.Vertex(new THREE.Vector3(x, y, z));\r
+  }\r
+  \r
+  var createAxis = function (p1, p2, color) {\r
+    var lineGeometry = new THREE.Geometry();\r
+    var lineMat = new THREE.LineBasicMaterial({ color: color, lineWidth: 2 });\r
+    lineGeometry.vertices.push(p1, p2);\r
+    var line = new THREE.Line(lineGeometry, lineMat);\r
+    scene.add(line);\r
+  }\r
+  \r
+  createAxis(v(0, 0, 0), v(axisLength, 0, 0), 0xFF0000);\r
+  createAxis(v(0, 0, 0), v(0, axisLength, 0), 0x00FF00);\r
+  createAxis(v(0, 0, 0), v(0, 0, axisLength), 0x0000FF);\r
+};\r
 \r
-    window.addEventListener('resize', set3dsize, false);\r
-    scene.add(camera);\r
-    set3dsize();\r
+function drawNodes(nodes) {\r
+  var geometry = new THREE.Geometry();\r
+  var center = getCenter(nodes);\r
+  \r
+  onResize();\r
+  for (var i = 0; i < nodes.length; i++) {\r
+    var material = new THREE.ParticleCanvasMaterial({\r
+      color: 0xffffff,\r
+      program: function (context) {\r
+        context.beginPath();\r
+        context.arc(0, 0, 1, 0, Math.PI * 2, true);\r
+        context.closePath();\r
+        context.fill();\r
+      }\r
+    });\r
+    var particle = new THREE.Particle(material);\r
+    particle.name = nodes[i][0];\r
+    particle.position.x = nodes[i][1] - center.x;\r
+    particle.position.y = nodes[i][2] - center.y;\r
+    particle.position.z = nodes[i][3] - center.z;\r
+    particle.uid = nodes[i][4];\r
+    particle.state = nodes[i][5];\r
+    particle.position.multiplyScalar(10);\r
+    particle.scale.x = particle.scale.y = 1;\r
+    scene.add(particle);\r
+    \r
+    var vertex = new THREE.Vertex(particle.position);\r
+    geometry.vertices.push(vertex);\r
+    objects.push(particle)\r
     \r
-\r
-    var PI2 = Math.PI * 2;\r
-    var geometry = new THREE.Geometry();\r
-\r
-    // let's find the center of the nodes\r
-    xmin = ymin = zmin = 0;\r
-    xmax = ymax = zmax = 0;\r
-\r
-    for (var i = 0; i < nodes_gre.length; i++) {\r
-        if (nodes_gre[i][1] > xmax) xmax = nodes_gre[i][1];\r
-        if (nodes_gre[i][1] < xmin) xmin = nodes_gre[i][1];\r
-        if (nodes_gre[i][2] > ymax) ymax = nodes_gre[i][2];\r
-        if (nodes_gre[i][2] < ymin) ymin = nodes_gre[i][2];\r
-        if (nodes_gre[i][3] > zmax) zmax = nodes_gre[i][3];\r
-        if (nodes_gre[i][3] < zmin) zmin = nodes_gre[i][3];\r
-    }\r
-\r
-    xcenter = (xmax + xmin) / 2;\r
-    ycenter = (ymax + ymin) / 2;\r
-    zcenter = (zmax + zmin) / 2;\r
-\r
-    // display nodes as TREE particles\r
-    for (var i = 0; i < nodes_gre.length; i++) {\r
-        material = new THREE.ParticleCanvasMaterial({\r
-            color: 0xffffff,\r
-            program: function (context) {\r
-                context.beginPath();\r
-                context.arc(0, 0, 1, 0, PI2, true);\r
-                context.closePath();\r
-                context.fill();\r
-            }\r
-        });\r
-        particle = new THREE.Particle(material);\r
-        particle.name = nodes_gre[i][0];\r
-        particle.position.x = nodes_gre[i][1] - xcenter;\r
-        particle.position.y = nodes_gre[i][2] - ycenter;\r
-        particle.position.z = nodes_gre[i][3] - zcenter;\r
-        particle.position.multiplyScalar(10);\r
-        particle.scale.x = particle.scale.y = 1;\r
-        scene.add(particle);\r
-        v = new THREE.Vertex(particle.position);\r
-        geometry.vertices.push(v);\r
-        objects.push(particle)\r
-    }\r
-\r
     debugaxis(10);\r
-    // a projector is needed to find which node is under the mouse\r
-    projector = new THREE.Projector();\r
-\r
-    nodebox.onkeyup = parseNodebox;\r
-    // set mouse event handlers // TODO jordan\r
-    document.onmousedown = OnMouseDown;\r
-    document.onmouseup = OnMouseUp;\r
-    document.onmousemove = displayNodeInfo;\r
-    if (window.addEventListener)\r
-    /** DOMMouseScroll is for mozilla. */\r
-        window.addEventListener('DOMMouseScroll', wheel, false);\r
-    /** IE/Opera. */\r
-    window.onmousewheel = document.onmousewheel = wheel;\r
     myrender();\r
+  }\r
 }\r
 \r
-function set3dsize() {\r
-    // jordan\r
-    var offset = div3d.offset();\r
-    offY = offset.top;\r
-    offX = offset.left;\r
-    window3DWidth = div3d.width();\r
-    window3DHeight = div3d.height();\r
-    renderer.setSize(window3DWidth, window3DHeight);\r
-\r
-    camera.aspect = window3DWidth / window3DHeight;\r
-    camera.updateProjectionMatrix();\r
-\r
-    myrender();\r
+function init(nodes) {\r
+  div3d = document.getElementById('div3d');\r
+  nodebox = document.getElementById('nodebox');\r
+  infobox = document.getElementById('infobox');\r
+  \r
+  infobox.innerHTML = 'Node info : ';\r
+  nodebox.value = "";\r
+  \r
+  camera = new THREE.PerspectiveCamera(75, div3d.offsetWidth / div3d.offsetHeight, 1, 10000);\r
+  scene = new THREE.Scene();\r
+  renderer = new THREE.CanvasRenderer();\r
+  projector = new THREE.Projector();\r
+  \r
+  div3d.appendChild(renderer.domElement);\r
+  \r
+  window.addEventListener('resize', onResize, false);\r
+  scene.add(camera);\r
+  \r
+  nodebox.onkeyup = parseNodebox;\r
+  \r
+  div3d.onmousedown = OnMouseDown;\r
+  div3d.onmouseup = OnMouseUp;\r
+  div3d.onmousemove = displayNodeInfo;\r
+  if (div3d.addEventListener) {\r
+    div3d.addEventListener('DOMMouseScroll', wheel, false); // mozilla\r
+  }\r
+  div3d.onmousewheel = wheel; // IE & Opera\r
 }\r
 \r
 function sortfunction(a, b) {\r
-    return (a - b) //causes an array to be sorted numerically and ascending\r
+  return (a - b) //causes an array to be sorted numerically and ascending\r
 }\r
 \r
 // factorize the expanded list in selectedNode to produce dash intervals\r
 // 1,2,3,5,9  -> 1-3,5,9\r
 function factorize() {\r
-    var fact = [];\r
-    var previous = 0;\r
-    var intervalStart = 0;\r
-    selectedNodes.sort(sortfunction);\r
-    for (j = 0; j < selectedNodes.length; j++) {\r
-        if (intervalStart) {\r
-            // we are in an interval\r
-            if (selectedNodes[j] == previous + 1) {\r
-                // interval grows\r
-                previous += 1;\r
-            } else {\r
-                // end of interval\r
-                fact.push(intervalStart + "-" + previous);\r
-                intervalStart = 0;\r
-                previous = selectedNodes[j];\r
-            }\r
-        } else {\r
-            // we are not in an interval\r
-            if (selectedNodes[j] == previous + 1) {\r
-                // let's begin an interval\r
-                intervalStart = previous;\r
-                previous += 1;\r
-            } else {\r
-                if (previous) fact.push(previous);\r
-                previous = selectedNodes[j];\r
-            }\r
-        }\r
-    } // for end \r
-    // at the end of the loop, two cases\r
-    // we were still in an interval, then add it to the result\r
-    // we were not in an interval, then add the last selectednode (previous)\r
+  var fact = [];\r
+  var previous = 0;\r
+  var intervalStart = 0;\r
+  selectedNodes.sort(sortfunction);\r
+  for (j = 0; j < selectedNodes.length; j++) {\r
     if (intervalStart) {\r
+      // we are in an interval\r
+      if (selectedNodes[j] == previous + 1) {\r
+        // interval grows\r
+        previous += 1;\r
+      } else {\r
+        // end of interval\r
         fact.push(intervalStart + "-" + previous);\r
+        intervalStart = 0;\r
+        previous = selectedNodes[j];\r
+      }\r
     } else {\r
-        if (previous) fact.push(previous);\r
+      // we are not in an interval\r
+      if (selectedNodes[j] == previous + 1) {\r
+        // let's begin an interval\r
+        intervalStart = previous;\r
+        previous += 1;\r
+      } else {\r
+        if (previous) {\r
+          fact.push(previous);\r
+        }\r
+        previous = selectedNodes[j];\r
+      }\r
     }\r
-    return fact;\r
+  } // for end\r
+  // at the end of the loop, two cases\r
+  // we were still in an interval, then add it to the result\r
+  // we were not in an interval, then add the last selectednode (previous)\r
+  if (intervalStart) {\r
+    fact.push(intervalStart + "-" + previous);\r
+  } else if (previous) {\r
+    fact.push(previous);\r
+  }\r
+  return fact;\r
 }\r
 \r
 // expand a list of nodes containing dash intervals\r
 // 1-3,5,9 -> 1,2,3,5,9\r
-function expand(factExp) {\r
-    exp = [];\r
-    for (i = 0; i < factExp.length; i++) {\r
-        dashExpression = factExp[i].split("-");\r
-        if (dashExpression.length == 2) {\r
-            for (j = parseInt(dashExpression[0]); j < (parseInt(dashExpression[1]) + 1); j++)\r
-                exp.push(j);\r
-        } else exp.push(parseInt(factExp[i]));\r
+function expand(input) {\r
+  var factorized = input.split(",");\r
+  var expanded = [];\r
+  for (var i = 0; i < factorized.length; i++) {\r
+    var d = factorized[i].split("-");\r
+    if (d.length == 2) {\r
+      for (var j = parseInt(d[0]); j < parseInt(d[1]) + 1; j++) {\r
+        expanded.push(j);\r
+      }\r
+    } else {\r
+      expanded.push(parseInt(factorized[i]));\r
+    }\r
+  }\r
+  expanded.sort(sortfunction);\r
+  for (var i = 1; i < expanded.length; i++) {\r
+    if (expanded[i] == expanded[i - 1]) {\r
+      expanded.splice(i--, 1);\r
     }\r
-    exp.sort(sortfunction);\r
-    for (var i = 1; i < exp.length; i++) { if (exp[i] == exp[i - 1]) { exp.splice(i--, 1); } }\r
-    return exp;\r
+  }\r
+  return expanded;\r
 }\r
 \r
 function parseNodebox() {\r
-    input = nodebox.value;\r
-    selectedNodes = expand(input.split(","));\r
-    myrender();\r
+  selectedNodes = expand(nodebox.value);\r
+  myrender();\r
 }\r
 \r
-function debugaxis(axisLength) {\r
-    //Shorten the vertex function\r
-    function v(x, y, z) {\r
-        return new THREE.Vertex(new THREE.Vector3(x, y, z));\r
-    }\r
-\r
-    //Create axis (point1, point2, colour)\r
-    function createAxis(p1, p2, color) {\r
-        var line, lineGeometry = new THREE.Geometry(),\r
-                    lineMat = new THREE.LineBasicMaterial({ color: color, lineWidth: 2 });\r
-        lineGeometry.vertices.push(p1, p2);\r
-        line = new THREE.Line(lineGeometry, lineMat);\r
-        scene.add(line);\r
-    }\r
-\r
-    createAxis(v(0, 0, 0), v(axisLength, 0, 0), 0xFF0000);\r
-    createAxis(v(0, 0, 0), v(0, axisLength, 0), 0x00FF00);\r
-    createAxis(v(0, 0, 0), v(0, 0, axisLength), 0x0000FF);\r
-};\r
-\r
 // set the camera position according two angles theta and phi and the distance\r
 // and display the scene\r
 function myrender() {\r
-    //infobox.innerHTML = " Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z\r
-    //                + " - " + theta + "," + phi + ","+ distance;\r
-    //infobox.innerHTML = selectedNodes;\r
-    camera.position.x = distance * Math.sin(theta * Math.PI / 360) * Math.cos(phi * Math.PI / 360);\r
-    camera.position.y = distance * Math.sin(this.phi * Math.PI / 360);\r
-    camera.position.z = distance * Math.cos(this.theta * Math.PI / 360) * Math.cos(this.phi * Math.PI / 360);\r
-    camera.lookAt(scene.position);\r
-    camera.updateMatrix();\r
-\r
-    for (i = 0; i < objects.length; i++)\r
-        if (selectedNodes.indexOf(objects[i].name) != -1) objects[i].material.color.setHex(0xff0000);\r
-        else objects[i].material.color.setHex(0xffffff);\r
-    renderer.render(scene, camera);\r
+  camera.position.x = distance * Math.sin(theta * Math.PI / 360) * Math.cos(phi * Math.PI / 360);\r
+  camera.position.y = distance * Math.sin(this.phi * Math.PI / 360);\r
+  camera.position.z = distance * Math.cos(this.theta * Math.PI / 360) * Math.cos(this.phi * Math.PI / 360);\r
+  camera.lookAt(scene.position);\r
+  camera.updateMatrix();\r
+  \r
+  for (i = 0; i < objects.length; i++) {\r
+    if (selectedNodes.indexOf(objects[i].name) != -1) {\r
+      objects[i].material.color.setHex(0x0099CC);\r
+    } else {\r
+      if (objects[i].state == "Busy") {\r
+        objects[i].material.color.setHex(0x9943BE);\r
+      } else if (objects[i].state == "Alive") {\r
+        objects[i].material.color.setHex(0x7FFF00);\r
+      } else {\r
+        objects[i].material.color.setHex(0xFF3030);\r
+      }\r
+    }\r
+  }\r
+  renderer.render(scene, camera);\r
 }\r
 \r
-// rigthbutton is used for rotations \r
+// rigthbutton is used for rotations\r
 function onDocumentMouseMoveRot(event) {\r
-    NewmouseX = event.clientX;\r
-    NewmouseY = event.clientY;\r
-    DeltaX = NewmouseX - mouseX;\r
-    DeltaY = NewmouseY - mouseY;\r
-\r
-    mouseX = NewmouseX;\r
-    mouseY = NewmouseY;\r
-\r
-    theta -= DeltaX;\r
-    phi += DeltaY;\r
-    if (phi > 180) phi = 180;\r
-    if (phi < -180) phi = -180;\r
-    myrender();\r
+  var NewmouseX = event.clientX;\r
+  var NewmouseY = event.clientY;\r
+  var DeltaX = NewmouseX - mouseX;\r
+  var DeltaY = NewmouseY - mouseY;\r
+  \r
+  mouseX = NewmouseX;\r
+  mouseY = NewmouseY;\r
+  \r
+  theta -= DeltaX;\r
+  phi += DeltaY;\r
+  if (phi > 180) phi = 180;\r
+  if (phi < -180) phi = -180;\r
+  myrender();\r
 }\r
 // mousewheel is used for zoom\r
 function Zoom(delta) {\r
-    distance += delta * 5;\r
-    myrender();\r
+  distance += delta * 5;\r
+  myrender();\r
 }\r
 \r
 // return the graphical node under the mouse\r
 function findNodeUnderMouse(event) {\r
-    var vector = new THREE.Vector3(((event.clientX - offX) / window3DWidth) * 2 - 1, -((event.clientY - offY) / window3DHeight) * 2 + 1, 0.5);\r
-    projector.unprojectVector(vector, camera);\r
-    var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize());\r
-    var intersects = ray.intersectObjects(objects);\r
-    if (intersects.length > 0) {\r
-        return intersects[0];\r
-    } else return null;\r
+  var x, y, z;\r
+  \r
+  event.preventDefault();\r
+  \r
+  x = ((event.clientX - div3d.offsetLeft) / div3d.offsetWidth) * 2 - 1;\r
+  y = -((event.clientY - div3d.offsetTop) / div3d.offsetHeight) * 2 + 1;\r
+  z = 0.5;\r
+  \r
+  var vector = new THREE.Vector3(x, y, z);\r
+  projector.unprojectVector(vector, camera);\r
+  \r
+  var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize());\r
+  var intersects = ray.intersectObjects(objects);\r
+  \r
+  if (intersects.length > 0) {\r
+    return intersects[0];\r
+  } else {\r
+    return null;\r
+  }\r
 }\r
 \r
 // display some info of the node under the mouse\r
 function displayNodeInfo(e) {\r
-    obj = findNodeUnderMouse(e);\r
-    if (obj) infobox.innerHTML = 'Node info : number ' + obj.object.name + " with id " + nodes_gre[obj.object.id][4];\r
-    //    else infobox.innerHTML = e.clientX + "," + e.clientY + " - " + offX + "," + offY;\r
+  obj = findNodeUnderMouse(e);\r
+  if (obj) {\r
+    infobox.innerHTML = 'Node info : number ' + obj.object.name + " with id " + obj.object.uid;\r
+  }\r
 }\r
 \r
 // select/unselect nodes\r
 function toggleNode(obj) {\r
-    nodeId = obj.object.name;\r
-    i = selectedNodes.indexOf(nodeId);\r
-    if (i == -1) selectedNodes.push(nodeId);\r
-    else selectedNodes.splice(i, 1);\r
-    nodebox.value = factorize().join(",");\r
-    myrender();\r
+  var nodeId = obj.object.name;\r
+  var index = selectedNodes.indexOf(nodeId);\r
+  \r
+  if (index == -1) {\r
+    selectedNodes.push(nodeId);\r
+  } else {\r
+    selectedNodes.splice(index, 1);\r
+  }\r
+  nodebox.value = factorize().join(",");\r
+  myrender();\r
 }\r
 \r
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
 // Mouse handling functions\r
 //\r
 function OnMouseDown(e) {\r
-    var clickType = 'LEFT';\r
-    if (e.type != sTestEventType) return true\r
+  var clickType = 'LEFT';\r
+  if (e.type != 'mousedown') return true\r
     if (e.which) {\r
-        if (e.which == 3) clickType = 'RIGHT';\r
-        if (e.which == 2) clickType = 'MIDDLE';\r
-        //infobox.innerHTML = clickType + " - Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z;\r
+      if (e.which == 3) clickType = 'RIGHT';\r
+      if (e.which == 2) clickType = 'MIDDLE';\r
+      //infobox.innerHTML = clickType + " - Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z;\r
     }\r
     mouseX = e.clientX;\r
-    mouseY = e.clientY;\r
-    if (clickType == 'RIGHT') {\r
-        document.onmousemove = onDocumentMouseMoveRot;\r
-    }\r
-    if (clickType == 'LEFT') {\r
-        obj = findNodeUnderMouse(e);\r
-        if (obj != null) toggleNode(obj);\r
-    }\r
+  mouseY = e.clientY;\r
+  if (clickType == 'RIGHT') {\r
+    document.onmousemove = onDocumentMouseMoveRot;\r
+  }\r
+  if (clickType == 'LEFT') {\r
+    obj = findNodeUnderMouse(e);\r
+    if (obj != null) toggleNode(obj);\r
+  }\r
 }\r
 \r
 function OnMouseUp(e) {\r
-    document.onmousemove = displayNodeInfo;\r
+  document.onmousemove = displayNodeInfo;\r
 }\r
 \r
 // This function was taken here : http://www.adomas.org/javascript-mouse-wheel/\r
 // Event handler for mouse wheel event.\r
 \r
 function wheel(event) {\r
-    var delta = 0;\r
-    if (!event) /* For IE. */\r
-        event = window.event;\r
-    if (event.wheelDelta) { /* IE/Opera. */\r
-        delta = event.wheelDelta / 120;\r
-    } else if (event.detail) { /** Mozilla case. */\r
-        /** In Mozilla, sign of delta is different than in IE.\r
-        * Also, delta is multiple of 3.\r
-        */\r
-        delta = -event.detail / 3;\r
-    }\r
-    /** If delta is nonzero, handle it.\r
-    * Basically, delta is now positive if wheel was scrolled up,\r
-    * and negative, if wheel was scrolled down.\r
-    */\r
-    if (delta)\r
-        Zoom(delta);\r
-    /** Prevent default actions caused by mouse wheel.\r
-    * That might be ugly, but we handle scrolls somehow\r
-    * anyway, so don't bother here..\r
-    */\r
-    if (event.preventDefault)\r
-        event.preventDefault();\r
-    event.returnValue = false;\r
-}          \r
+  var delta = 0;\r
+  if (!event) /* For IE. */\r
+    event = window.event;\r
+  if (event.wheelDelta) { /* IE/Opera. */\r
+    delta = event.wheelDelta / 120;\r
+  } else if (event.detail) { /** Mozilla case. */\r
+    /** In Mozilla, sign of delta is different than in IE.\r
+     * Also, delta is multiple of 3.\r
+     */\r
+    delta = -event.detail / 3;\r
+  }\r
+  /** If delta is nonzero, handle it.\r
+   * Basically, delta is now positive if wheel was scrolled up,\r
+   * and negative, if wheel was scrolled down.\r
+   */\r
+  if (delta)\r
+    Zoom(delta);\r
+  /** Prevent default actions caused by mouse wheel.\r
+   * That might be ugly, but we handle scrolls somehow\r
+   * anyway, so don't bother here..\r
+   */\r
+  if (event.preventDefault)\r
+    event.preventDefault();\r
+  event.returnValue = false;\r
+}\r