diff --git a/js/elementMenu.js b/js/elementMenu.js
index e1d11d4ca8ce37b678c7c1a1790056a017b4eead..89012de9dbbb09bc245b78595b614eaefbd16436 100644
--- a/js/elementMenu.js
+++ b/js/elementMenu.js
@@ -6,6 +6,7 @@ $(function(){
 
     three = three || {};
     modelMesh = modelMesh || {};
+    workers = workers || {};
 
     $("#elementCube").click(function(e){
         e.preventDefault();
@@ -19,13 +20,16 @@ $(function(){
            xRange.push(x);
         }
 
-        workers.options.env = {boundingBox:boundingBox,
-        three:three,
+        var localEnv = {boundingBox:boundingBox,
         cubeDim:cubeDim,
         modelMesh:modelMesh};
-        workers.data = xRange;
 
-        workers.map(fillWithElements).then(addToScene);//.reduce(merge).
+        workers.map(xRange, fillWithElements, localEnv, incrCallback);
+
+
+        function incrCallback(result){
+            console.log(result);
+        }
 
         function merge(meshes){
             var allMeshes = meshes[1];
@@ -45,29 +49,27 @@ $(function(){
         }
 
         function fillWithElements(x){
-            console.log("here");
             var meshesToAdd = [];
-            var cubeDim = global.env.cubeDim;
-            var boundingBox = global.env.boundingBox;
-            var clone = new THREE.Mesh(global.env.modelMesh.geometry, global.env.modelMesh.material);//this sucks, but modelMesh is missing properties for now
-            for (var y=boundingBox.min.y;y<boundingBox.max.y;y+=cubeDim){
-//                if ()
-                for (var z=boundingBox.min.z;z<boundingBox.max.z;z+=cubeDim){
-                    var raycaster = new THREE.Raycaster(new THREE.Vector3(x+cubeDim/2, y+cubeDim/2, z+cubeDim/2),
-                        new THREE.Vector3(0, 0, 1), 0, boundingBox.max.z-z+cubeDim/2);
-                    var numIntersections = raycaster.intersectObject(clone).length;
-                    if (numIntersections % 2 == 1) {
-                        var mesh = createCubeGeometry(cubeDim);
-                        mesh.position.set(x+cubeDim/2, y+cubeDim/2, z+cubeDim/2);
-                        mesh.updateMatrix();
-                        mesh.matrixAutoUpdate = false;
-                        meshesToAdd.push(mesh);
-                        global.env.three.scene.add(mesh);
-                    } else if (numIntersections == 0){
-                    }
-                }
-            }
-            return meshesToAdd;
+            var cubeDim = localEnv.cubeDim;
+            var boundingBox = localEnv.boundingBox;
+//            for (var y=boundingBox.min.y;y<boundingBox.max.y;y+=cubeDim){
+////                if ()
+//                for (var z=boundingBox.min.z;z<boundingBox.max.z;z+=cubeDim){
+//                    var raycaster = new THREE.Raycaster(new THREE.Vector3(x+cubeDim/2, y+cubeDim/2, z+cubeDim/2),
+//                        new THREE.Vector3(0, 0, 1), 0, boundingBox.max.z-z+cubeDim/2);
+//                    var numIntersections = raycaster.intersectObject(localEnv.modelMesh).length;
+//                    if (numIntersections % 2 == 1) {
+//                        var mesh = createCubeGeometry(cubeDim);
+//                        mesh.position.set(x+cubeDim/2, y+cubeDim/2, z+cubeDim/2);
+//                        mesh.updateMatrix();
+//                        mesh.matrixAutoUpdate = false;
+//                        meshesToAdd.push(mesh);
+////                        global.env.three.scene.add(mesh);
+//                    } else if (numIntersections == 0){
+//                    }
+//                }
+//            }
+            return x*x;
         }
     });
 
diff --git a/js/main.js b/js/main.js
index b21a89931afafcf7974590a89ef461305458e5d3..40dad3cbf52c229f6558f52f7e3f44a871b62dc4 100644
--- a/js/main.js
+++ b/js/main.js
@@ -9,14 +9,6 @@ $(function(){
     setupNavBar();
     workers = persistentWorkers(8);
 
-    workers.map([11,12], executable, {}, incrCallback);
 
-    function executable(){
-        return arg*arg;
-    }
-
-    function incrCallback(result){
-        console.log(result);
-    }
 
 });
diff --git a/js/persistentWorkers.js b/js/persistentWorkers.js
index 289fb28bb94f3645a3aebf3339bca4a3ffdaefd3..79d805e9d6eca26006b5ce136a41b34bb6607636 100644
--- a/js/persistentWorkers.js
+++ b/js/persistentWorkers.js
@@ -23,16 +23,32 @@ function persistentWorkers(numWorkers){
     }
     URL.revokeObjectURL(workerURL);
 
-    function map(data, executable, env, incrCallback){
-
-        //save args in map queue
-        mapQueue.push({data:data, executable:executable, env:env, index:0, incrCallback:incrCallback, finished:false, activeThreads:0});
+    function map(data, executable, env, incrCallback, finalCallback){
+
+        //save new task in map queue
+        mapQueue.push({data:data,
+            executable:prepareExeFunc(executable.toString()),
+            env:env,
+            index:0,
+            incrCallback:incrCallback,
+            finalCallback:finalCallback,
+            finished:false,
+            activeThreads:0});
 
         for (var i=0;i<allWorkers.length;i++){
             allWorkers[i].postMessage({isWorking:true});//ask workers if they are busy
         }
     }
 
+    function prepareExeFunc(string){
+        var index = string.indexOf("(");//get index of first ( in function declaration
+        if (index == -1) {
+            console.log("exe function not formed properly for web workers " + string);
+            return null;
+        }
+        return "function executable" + string.substring(index);
+    }
+
     function onMessage(e){
 
         if (e.data.result){//handle result first
@@ -42,10 +58,10 @@ function persistentWorkers(numWorkers){
             var currentTask = mapQueue[0];
             currentTask.activeThreads--;//decrement active threads
 
-            currentTask.incrCallback(e.data.result);//incremental callback
+            if (currentTask.incrCallback) currentTask.incrCallback(e.data.result);//incremental callback
             if (currentTask.finished && currentTask.activeThreads == 0){
+                if (currentTask.finalCallback) currentTask.finalCallback();
                 mapQueue.shift();//remove first element
-                console.log("end of task");
             }
         }
 
@@ -67,8 +83,8 @@ function persistentWorkers(numWorkers){
             nextTask.activeThreads++;
             e.target.postMessage({
                 arg:nextTask.data[currentIndex],
-                localEnv:nextTask.env,
-                executable:nextTask.executable.toString()});
+                localEnv:JSON.stringify(nextTask.env),
+                executable:nextTask.executable});
         }
     }
 
@@ -83,11 +99,6 @@ function persistentWorkers(numWorkers){
         }
     }
 
-
-    function incrementalCallback(){
-
-    }
-
     function makeBlobURL(URL, someFunction) {
         var blob = new Blob(["(" + someFunction.toString() + ")()"], { type: "text/javascript" });
         return URL.createObjectURL(blob);
diff --git a/js/worker.js b/js/worker.js
index 154f9e944b82b852b8f0b7e738c64dc2355cc3ba..97fc8fd406c866d916b9ed14a5365748477c200f 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -30,7 +30,7 @@ function myWorker(){
         if (data.executable){
 
             if (data.localEnv){//be sure to get local environment vars before executable runs
-                localEnv = data.localEnv;
+                localEnv = JSON.parse(data.localEnv);
             }
             if (data.arg){//be sure to get arg before executable runs
                 arg = data.arg;
@@ -42,7 +42,7 @@ function myWorker(){
             }
             working = true;
             eval(data.executable);
-            var result = executable();
+            var result = executable(arg);
             working = false;
             postMessage({result:result, isWorking:working});
         }