1 Thingiview = function(containerId
) {
4 this.containerId
= containerId
;
5 var container
= document
.getElementById(containerId
);
14 var ambientLight
= null;
15 var directionalLight
= null;
16 var pointLight
= null;
18 var targetXRotation
= 0;
19 var targetXRotationOnMouseDown
= 0;
21 var mouseXOnMouseDown
= 0;
23 var targetYRotation
= 0;
24 var targetYRotationOnMouseDown
= 0;
26 var mouseYOnMouseDown
= 0;
28 var mouseDown
= false;
29 var mouseOver
= false;
31 var windowHalfX
= window
.innerWidth
/ 2;
32 var windowHalfY
= window
.innerHeight
/ 2
35 var infoMessage
= null;
36 var progressBar
= null;
41 var rotateTimer
= null;
42 var rotateListener
= null;
43 var wasRotating
= null;
45 var cameraView
= 'diagonal';
48 var backgroundColor
= '#606060';
49 var objectMaterial
= 'solid';
50 var objectColor
= 0xffffff;
54 if (document
.defaultView
&& document
.defaultView
.getComputedStyle
) {
55 var width
= parseFloat(document
.defaultView
.getComputedStyle(container
,null).getPropertyValue('width'));
56 var height
= parseFloat(document
.defaultView
.getComputedStyle(container
,null).getPropertyValue('height'));
58 var width
= parseFloat(container
.currentStyle
.width
);
59 var height
= parseFloat(container
.currentStyle
.height
);
64 this.initScene = function() {
65 container
.style
.position
= 'relative';
66 container
.innerHTML
= '';
68 camera
= new THREE
.Camera(45, width
/ height
, 1, 100000);
69 camera
.updateMatrix();
71 scene
= new THREE
.Scene();
73 ambientLight
= new THREE
.AmbientLight(0x202020);
74 scene
.addLight(ambientLight
);
76 directionalLight
= new THREE
.DirectionalLight(0xffffff, 0.75);
77 directionalLight
.position
.x
= 1;
78 directionalLight
.position
.y
= 1;
79 directionalLight
.position
.z
= 2;
80 directionalLight
.position
.normalize();
81 scene
.addLight(directionalLight
);
83 pointLight
= new THREE
.PointLight(0xffffff, 0.3);
84 pointLight
.position
.x
= 0;
85 pointLight
.position
.y
= -25;
86 pointLight
.position
.z
= 10;
87 scene
.addLight(pointLight
);
89 progressBar
= document
.createElement('div');
90 progressBar
.style
.position
= 'absolute';
91 progressBar
.style
.top
= '0px';
92 progressBar
.style
.left
= '0px';
93 progressBar
.style
.backgroundColor
= 'red';
94 progressBar
.style
.padding
= '5px';
95 progressBar
.style
.display
= 'none';
96 progressBar
.style
.overflow
= 'visible';
97 progressBar
.style
.whiteSpace
= 'nowrap';
98 progressBar
.style
.zIndex
= 100;
99 container
.appendChild(progressBar
);
101 alertBox
= document
.createElement('div');
102 alertBox
.id
= 'alertBox';
103 alertBox
.style
.position
= 'absolute';
104 alertBox
.style
.top
= '25%';
105 alertBox
.style
.left
= '25%';
106 alertBox
.style
.width
= '50%';
107 alertBox
.style
.height
= '50%';
108 alertBox
.style
.backgroundColor
= '#dddddd';
109 alertBox
.style
.padding
= '10px';
110 // alertBox.style.overflowY = 'scroll';
111 alertBox
.style
.display
= 'none';
112 alertBox
.style
.zIndex
= 100;
113 container
.appendChild(alertBox
);
115 // load a blank object
116 // this.loadSTLString('');
122 this.setCameraView(cameraView
);
123 this.setObjectMaterial(objectMaterial
);
125 testCanvas
= document
.createElement('canvas');
127 if (testCanvas
.getContext('experimental-webgl')) {
128 // showPlane = false;
130 renderer
= new THREE
.WebGLRenderer();
131 // renderer = new THREE.CanvasRenderer();
133 renderer
= new THREE
.CanvasRenderer();
136 renderer
= new THREE
.CanvasRenderer();
137 // log("failed webgl detection");
140 // renderer.setSize(container.innerWidth, container.innerHeight);
142 renderer
.setSize(width
, height
);
143 renderer
.domElement
.style
.backgroundColor
= backgroundColor
;
144 container
.appendChild(renderer
.domElement
);
146 // stats = new Stats();
147 // stats.domElement.style.position = 'absolute';
148 // stats.domElement.style.top = '0px';
149 // container.appendChild(stats.domElement);
151 // TODO: figure out how to get the render window to resize when window resizes
152 // window.addEventListener('resize', onContainerResize(), false);
153 // container.addEventListener('resize', onContainerResize(), false);
155 // renderer.domElement.addEventListener('mousemove', onRendererMouseMove, false);
156 window
.addEventListener('mousemove', onRendererMouseMove
, false);
157 renderer
.domElement
.addEventListener('mouseover', onRendererMouseOver
, false);
158 renderer
.domElement
.addEventListener('mouseout', onRendererMouseOut
, false);
159 renderer
.domElement
.addEventListener('mousedown', onRendererMouseDown
, false);
160 // renderer.domElement.addEventListener('mouseup', onRendererMouseUp, false);
161 window
.addEventListener('mouseup', onRendererMouseUp
, false);
163 renderer
.domElement
.addEventListener('touchstart', onRendererTouchStart
, false);
164 renderer
.domElement
.addEventListener('touchend', onRendererTouchEnd
, false);
165 renderer
.domElement
.addEventListener('touchmove', onRendererTouchMove
, false);
167 renderer
.domElement
.addEventListener('DOMMouseScroll', onRendererScroll
, false);
168 renderer
.domElement
.addEventListener('mousewheel', onRendererScroll
, false);
169 renderer
.domElement
.addEventListener('gesturechange', onRendererGestureChange
, false);
173 // onContainerResize = function(event) {
174 // width = parseFloat(document.defaultView.getComputedStyle(container,null).getPropertyValue('width'));
175 // height = parseFloat(document.defaultView.getComputedStyle(container,null).getPropertyValue('height'));
177 // // log("resized width: " + width + ", height: " + height);
180 // renderer.setSize(width, height);
181 // camera.projectionMatrix = THREE.Matrix4.makePerspective(70, width / height, 1, 10000);
186 onRendererScroll = function(event
) {
187 event
.preventDefault();
191 if (event
.wheelDelta
=== undefined) {
193 // The measurement units of the detail and wheelDelta properties are different.
194 rolled
= -40 * event
.detail
;
196 rolled
= event
.wheelDelta
;
201 scope
.setCameraZoom(+10);
204 scope
.setCameraZoom(-10);
208 onRendererGestureChange = function(event
) {
209 event
.preventDefault();
211 if (event
.scale
> 1) {
212 scope
.setCameraZoom(+5);
214 scope
.setCameraZoom(-5);
218 onRendererMouseOver = function(event
) {
220 // targetRotation = object.rotation.z;
222 // log('starting loop');
223 timer
= setInterval(sceneLoop
, 1000/60);
227 onRendererMouseDown = function(event
) {
230 event
.preventDefault();
233 if(scope
.getRotation()){
235 scope
.setRotation(false);
240 mouseXOnMouseDown
= event
.clientX
- windowHalfX
;
241 mouseYOnMouseDown
= event
.clientY
- windowHalfY
;
243 targetXRotationOnMouseDown
= targetXRotation
;
244 targetYRotationOnMouseDown
= targetYRotation
;
247 onRendererMouseMove = function(event
) {
251 mouseX
= event
.clientX
- windowHalfX
;
252 // targetXRotation = targetXRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;
253 xrot
= targetXRotationOnMouseDown
+ (mouseX
- mouseXOnMouseDown
) * 0.02;
255 mouseY
= event
.clientY
- windowHalfY
;
256 // targetYRotation = targetYRotationOnMouseDown + (mouseY - mouseYOnMouseDown) * 0.02;
257 yrot
= targetYRotationOnMouseDown
+ (mouseY
- mouseYOnMouseDown
) * 0.02;
259 targetXRotation
= xrot
;
260 targetYRotation
= yrot
;
264 onRendererMouseUp = function(event
) {
269 clearInterval(timer
);
273 scope
.setRotation(true);
278 onRendererMouseOut = function(event
) {
280 clearInterval(timer
);
286 onRendererTouchStart = function(event
) {
287 targetXRotation
= object
.rotation
.z
;
288 targetYRotation
= object
.rotation
.x
;
290 timer
= setInterval(sceneLoop
, 1000/60);
292 if (event
.touches
.length
== 1) {
293 event
.preventDefault();
295 mouseXOnMouseDown
= event
.touches
[0].pageX
- windowHalfX
;
296 targetXRotationOnMouseDown
= targetXRotation
;
298 mouseYOnMouseDown
= event
.touches
[0].pageY
- windowHalfY
;
299 targetYRotationOnMouseDown
= targetYRotation
;
303 onRendererTouchEnd = function(event
) {
304 clearInterval(timer
);
306 // targetXRotation = object.rotation.z;
307 // targetYRotation = object.rotation.x;
310 onRendererTouchMove = function(event
) {
311 if (event
.touches
.length
== 1) {
312 event
.preventDefault();
314 mouseX
= event
.touches
[0].pageX
- windowHalfX
;
315 targetXRotation
= targetXRotationOnMouseDown
+ (mouseX
- mouseXOnMouseDown
) * 0.05;
317 mouseY
= event
.touches
[0].pageY
- windowHalfY
;
318 targetYRotation
= targetYRotationOnMouseDown
+ (mouseY
- mouseYOnMouseDown
) * 0.05;
322 sceneLoop = function() {
324 // if (view == 'bottom') {
326 // plane.rotation.z = object.rotation.z -= (targetRotation + object.rotation.z) * 0.05;
328 // object.rotation.z -= (targetRotation + object.rotation.z) * 0.05;
332 // plane.rotation.z = object.rotation.z += (targetRotation - object.rotation.z) * 0.05;
334 // object.rotation.z += (targetRotation - object.rotation.z) * 0.05;
339 plane
.rotation
.z
= object
.rotation
.z
= (targetXRotation
- object
.rotation
.z
) * 0.2;
340 plane
.rotation
.x
= object
.rotation
.x
= (targetYRotation
- object
.rotation
.x
) * 0.2;
342 object
.rotation
.z
= (targetXRotation
- object
.rotation
.z
) * 0.2;
343 object
.rotation
.x
= (targetYRotation
- object
.rotation
.x
) * 0.2;
346 // log(object.rotation.x);
348 camera
.updateMatrix();
349 object
.updateMatrix();
352 plane
.updateMatrix();
355 renderer
.render(scene
, camera
);
360 rotateLoop = function() {
361 // targetRotation += 0.01;
362 targetXRotation
+= 0.05;
366 this.getShowPlane = function(){
370 this.setShowPlane = function(show
) {
374 if (scene
&& !plane
) {
377 plane
.material
[0].opacity
= 1;
378 // plane.updateMatrix();
380 if (scene
&& plane
) {
381 // alert(plane.material[0].opacity);
382 plane
.material
[0].opacity
= 0;
383 // plane.updateMatrix();
390 this.getRotation = function() {
391 return rotateTimer
!== null;
394 this.resetRotation = function () {
396 this.setRotation(false);
397 this.setRotation(true);
401 this.setRotation = function(rotate
) {
405 rotateTimer
= setInterval(rotateLoop
, 1000/60);
407 clearInterval(rotateTimer
);
411 scope
.onSetRotation();
414 this.onSetRotation = function(callback
) {
415 if(callback
=== undefined){
416 if(rotateListener
!== null){
418 rotateListener(scope
.getRotation());
422 rotateListener
= callback
;
426 this.setCameraView = function(dir
) {
433 object
.rotation
.x
= 0;
434 object
.rotation
.y
= 0;
435 object
.rotation
.z
= 0;
438 if (showPlane
&& object
) {
439 plane
.rotation
.x
= object
.rotation
.x
;
440 plane
.rotation
.y
= object
.rotation
.y
;
441 plane
.rotation
.z
= object
.rotation
.z
;
445 // camera.position.y = 0;
446 // camera.position.z = 100;
447 // camera.target.position.z = 0;
449 plane
.flipSided
= false;
451 } else if (dir
== 'side') {
452 // camera.position.y = -70;
453 // camera.position.z = 70;
454 // camera.target.position.z = 0;
455 targetYRotation
= -4.5;
457 plane
.flipSided
= false;
459 } else if (dir
== 'bottom') {
460 // camera.position.y = 0;
461 // camera.position.z = -100;
462 // camera.target.position.z = 0;
464 plane
.flipSided
= true;
467 // camera.position.y = -70;
468 // camera.position.z = 70;
469 // camera.target.position.z = 0;
471 plane
.flipSided
= false;
475 mouseX
= targetXRotation
;
476 mouseXOnMouseDown
= targetXRotation
;
478 mouseY
= targetYRotation
;
479 mouseYOnMouseDown
= targetYRotation
;
481 scope
.centerCamera();
486 this.setCameraZoom = function(factor
) {
489 if (cameraView
== 'bottom') {
490 if (camera
.position
.z
+ factor
> 0) {
494 if (camera
.position
.z
- factor
< 0) {
499 if (cameraView
== 'top') {
500 camera
.position
.z
-= factor
;
501 } else if (cameraView
== 'bottom') {
502 camera
.position
.z
+= factor
;
503 } else if (cameraView
== 'side') {
504 camera
.position
.y
+= factor
;
505 camera
.position
.z
-= factor
;
507 camera
.position
.y
+= factor
;
508 camera
.position
.z
-= factor
;
514 this.getObjectMaterial = function() {
515 return objectMaterial
;
518 this.setObjectMaterial = function(type
) {
519 objectMaterial
= type
;
521 loadObjectGeometry();
524 this.setBackgroundColor = function(color
) {
525 backgroundColor
= color
528 renderer
.domElement
.style
.backgroundColor
= color
;
532 this.setObjectColor = function(color
) {
533 objectColor
= parseInt(color
.replace(/\#/g, ''), 16);
535 loadObjectGeometry();
538 this.loadSTL = function(url
) {
539 scope
.newWorker('loadSTL', url
);
542 this.loadOBJ = function(url
) {
543 scope
.newWorker('loadOBJ', url
);
546 this.loadSTLString = function(STLString
) {
547 scope
.newWorker('loadSTLString', STLString
);
550 this.loadSTLBinary = function(STLBinary
) {
551 scope
.newWorker('loadSTLBinary', STLBinary
);
554 this.loadOBJString = function(OBJString
) {
555 scope
.newWorker('loadOBJString', OBJString
);
558 this.loadJSON = function(url
) {
559 scope
.newWorker('loadJSON', url
);
562 this.loadPLY = function(url
) {
563 scope
.newWorker('loadPLY', url
);
566 this.loadPLYString = function(PLYString
) {
567 scope
.newWorker('loadPLYString', PLYString
);
570 this.loadPLYBinary = function(PLYBinary
) {
571 scope
.newWorker('loadPLYBinary', PLYBinary
);
574 this.centerCamera = function() {
576 // Using method from http://msdn.microsoft.com/en-us/library/bb197900(v=xnagamestudio.10).aspx
577 // log("bounding sphere radius = " + geometry.boundingSphere.radius);
579 // look at the center of the object
580 camera
.target
.position
.x
= geometry
.center_x
;
581 camera
.target
.position
.y
= geometry
.center_y
;
582 camera
.target
.position
.z
= geometry
.center_z
;
584 // set camera position to center of sphere
585 camera
.position
.x
= geometry
.center_x
;
586 camera
.position
.y
= geometry
.center_y
;
587 camera
.position
.z
= geometry
.center_z
;
589 // find distance to center
590 distance
= geometry
.boundingSphere
.radius
/ Math
.sin((camera
.fov
/2) * (Math.PI / 180));
592 // zoom backwards about half that distance, I don't think I'm doing the math or backwards vector calculation correctly?
593 // scope.setCameraZoom(-distance/1.8);
594 // scope.setCameraZoom(-distance/1.5);
595 scope
.setCameraZoom(-distance
/1.9);
597 directionalLight
.position
.x
= geometry
.min_y
* 2;
598 directionalLight
.position
.y
= geometry
.min_y
* 2;
599 directionalLight
.position
.z
= geometry
.max_z
* 2;
601 pointLight
.position
.x
= geometry
.center_y
;
602 pointLight
.position
.y
= geometry
.center_y
;
603 pointLight
.position
.z
= geometry
.max_z
* 2;
605 // set to any valid position so it doesn't fail before geometry is available
606 camera
.position
.y
= -70;
607 camera
.position
.z
= 70;
608 camera
.target
.position
.z
= 0;
612 this.loadArray = function(array
) {
613 log("loading array...");
614 geometry
= new STLGeometry(array
);
615 loadObjectGeometry();
616 scope
.resetRotation();
617 scope
.centerCamera();
618 log("finished loading " + geometry
.faces
.length
+ " faces.");
621 this.newWorker = function(cmd
, param
) {
622 scope
.setRotation(false);
624 var worker
= new WorkerFacade(thingiurlbase
+ '/thingiloader.js');
626 worker
.onmessage = function(event
) {
627 if (event
.data
.status
== "complete") {
628 progressBar
.innerHTML
= 'Initializing geometry...';
629 // scene.removeObject(object);
630 geometry
= new STLGeometry(event
.data
.content
);
631 loadObjectGeometry();
632 progressBar
.innerHTML
= '';
633 progressBar
.style
.display
= 'none';
635 scope
.resetRotation();
636 log("finished loading " + geometry
.faces
.length
+ " faces.");
637 scope
.centerCamera();
638 } else if (event
.data
.status
== "complete_points") {
639 progressBar
.innerHTML
= 'Initializing points...';
641 geometry
= new THREE
.Geometry();
643 var material
= new THREE
.ParticleBasicMaterial( { color
: 0xff0000, opacity
: 1 } );
645 // material = new THREE.ParticleBasicMaterial( { size: 35, sizeAttenuation: false} );
646 // material.color.setHSV( 1.0, 0.2, 0.8 );
648 for (i
in event
.data
.content
[0]) {
649 // for (var i=0; i<10; i++) {
650 vector
= new THREE
.Vector3( event
.data
.content
[0][i
][0], event
.data
.content
[0][i
][1], event
.data
.content
[0][i
][2] );
651 geometry
.vertices
.push( new THREE
.Vertex( vector
) );
654 particles
= new THREE
.ParticleSystem( geometry
, material
);
655 particles
.sortParticles
= true;
656 particles
.updateMatrix();
657 scene
.addObject( particles
);
659 camera
.updateMatrix();
660 renderer
.render(scene
, camera
);
662 progressBar
.innerHTML
= '';
663 progressBar
.style
.display
= 'none';
665 scope
.resetRotation();
666 log("finished loading " + event
.data
.content
[0].length
+ " points.");
667 // scope.centerCamera();
668 } else if (event
.data
.status
== "progress") {
669 progressBar
.style
.display
= 'block';
670 progressBar
.style
.width
= event
.data
.content
;
671 // log(event.data.content);
672 } else if (event
.data
.status
== "message") {
673 progressBar
.style
.display
= 'block';
674 progressBar
.innerHTML
= event
.data
.content
;
675 log(event
.data
.content
);
676 } else if (event
.data
.status
== "alert") {
677 scope
.displayAlert(event
.data
.content
);
679 alert('Error: ' + event
.data
);
680 log('Unknown Worker Message: ' + event
.data
);
684 worker
.onerror = function(error
) {
686 error
.preventDefault();
689 worker
.postMessage({'cmd':cmd
, 'param':param
});
692 this.displayAlert = function(msg
) {
693 msg
= msg
+ "<br/><br/><center><input type=\"button\" value=\"Ok\" onclick=\"document.getElementById('alertBox').style.display='none'\"></center>"
695 alertBox
.innerHTML
= msg
;
696 alertBox
.style
.display
= 'block';
701 function loadPlaneGeometry() {
702 // TODO: switch to lines instead of the Plane object so we can get rid of the horizontal lines in canvas renderer...
703 plane
= new THREE
.Mesh(new Plane(100, 100, 10, 10), new THREE
.MeshBasicMaterial({color
:0xafafaf,wireframe
:true}));
704 scene
.addObject(plane
);
707 function loadObjectGeometry() {
708 if (scene
&& geometry
) {
709 if (objectMaterial
== 'wireframe') {
710 // material = new THREE.MeshColorStrokeMaterial(objectColor, 1, 1);
711 material
= new THREE
.MeshBasicMaterial({color
:objectColor
,wireframe
:true});
714 // material = new THREE.MeshPhongMaterial(objectColor, objectColor, 0xffffff, 50, 1.0);
715 // material = new THREE.MeshColorFillMaterial(objectColor);
716 // material = new THREE.MeshLambertMaterial({color:objectColor});
717 material
= new THREE
.MeshLambertMaterial({color
:objectColor
, shading
: THREE
.FlatShading
});
719 // material = new THREE.MeshColorFillMaterial(objectColor);
720 material
= new THREE
.MeshLambertMaterial({color
:objectColor
, shading
: THREE
.FlatShading
});
724 // scene.removeObject(object);
727 // shouldn't be needed, but this fixes a bug with webgl not removing previous object when loading a new one dynamically
728 object
.materials
= [new THREE
.MeshBasicMaterial({color
:0xffffff, opacity
:0})];
729 scene
.removeObject(object
);
730 // object.geometry = geometry;
731 // object.materials = [material];
734 object
= new THREE
.Mesh(geometry
, material
);
735 scene
.addObject(object
);
737 if (objectMaterial
!= 'wireframe') {
738 object
.overdraw
= true;
739 object
.doubleSided
= true;
742 object
.updateMatrix();
753 var STLGeometry = function(stlArray
) {
754 // log("building geometry...");
755 THREE
.Geometry
.call(this);
759 // var vertexes = stlArray[0];
760 // var normals = stlArray[1];
761 // var faces = stlArray[2];
763 for (var i
=0; i
<stlArray
[0].length
; i
++) {
764 v(stlArray
[0][i
][0], stlArray
[0][i
][1], stlArray
[0][i
][2]);
767 for (var i
=0; i
<stlArray
[1].length
; i
++) {
768 f3(stlArray
[1][i
][0], stlArray
[1][i
][1], stlArray
[1][i
][2]);
771 function v(x
, y
, z
) {
772 // log("adding vertex: " + x + "," + y + "," + z);
773 scope
.vertices
.push( new THREE
.Vertex( new THREE
.Vector3( x
, y
, z
) ) );
776 function f3(a
, b
, c
) {
777 // log("adding face: " + a + "," + b + "," + c)
778 scope
.faces
.push( new THREE
.Face3( a
, b
, c
) );
781 // log("computing centroids...");
782 this.computeCentroids();
783 // log("computing normals...");
784 // this.computeNormals();
785 this.computeFaceNormals();
786 this.sortFacesByMaterial();
787 // log("finished building geometry");
797 for (var v
= 0, vl
= scope
.vertices
.length
; v
< vl
; v
++) {
798 scope
.max_x
= Math
.max(scope
.max_x
, scope
.vertices
[v
].position
.x
);
799 scope
.max_y
= Math
.max(scope
.max_y
, scope
.vertices
[v
].position
.y
);
800 scope
.max_z
= Math
.max(scope
.max_z
, scope
.vertices
[v
].position
.z
);
802 scope
.min_x
= Math
.min(scope
.min_x
, scope
.vertices
[v
].position
.x
);
803 scope
.min_y
= Math
.min(scope
.min_y
, scope
.vertices
[v
].position
.y
);
804 scope
.min_z
= Math
.min(scope
.min_z
, scope
.vertices
[v
].position
.z
);
807 scope
.center_x
= (scope
.max_x
+ scope
.min_x
)/2;
808 scope
.center_y
= (scope
.max_y
+ scope
.min_y
)/2;
809 scope
.center_z
= (scope
.max_z
+ scope
.min_z
)/2;
812 STLGeometry
.prototype = new THREE
.Geometry();
813 STLGeometry
.prototype.constructor = STLGeometry
;
821 /* A facade for the Web Worker API that fakes it in case it's missing.
822 Good when web workers aren't supported in the browser, but it's still fast enough, so execution doesn't hang too badly (e.g. Opera 10.5).
823 By Stefan Wehrmeyer, licensed under MIT
828 WorkerFacade
= (function(){
829 return function(path
){
830 return new window
.Worker(path
);
834 WorkerFacade
= (function(){
835 var workers
= {}, masters
= {}, loaded
= false;
836 var that = function(path
){
837 var theworker
= {}, loaded
= false, callings
= [];
838 theworker
.postToWorkerFunction = function(args
){
840 workers
[path
]({"data":args
});
842 theworker
.onerror(err
);
845 theworker
.postMessage = function(params
){
847 callings
.push(params
);
850 theworker
.postToWorkerFunction(params
);
852 masters
[path
] = theworker
;
853 var scr
= document
.createElement("SCRIPT");
855 scr
.type
= "text/javascript";
856 scr
.onload = function(){
858 while(callings
.length
> 0){
859 theworker
.postToWorkerFunction(callings
[0]);
863 document
.body
.appendChild(scr
);
865 var binaryscr
= document
.createElement("SCRIPT");
866 binaryscr
.src
= thingiurlbase
+ '/binaryReader.js';
867 binaryscr
.type
= "text/javascript";
868 document
.body
.appendChild(binaryscr
);
873 that
.add = function(pth
, worker
){
874 workers
[pth
] = worker
;
875 return function(param
){
876 masters
[pth
].onmessage({"data": param
});
879 that
.toString = function(){
880 return "FakeWorker('"+path
+"')";
886 /* Then just use WorkerFacade instead of Worker (or alias it)
888 The Worker code must should use a custom function (name it how you want) instead of postMessage.
889 Put this at the end of the Worker:
891 if(typeof(window) === "undefined"){
892 onmessage = nameOfWorkerFunction;
893 customPostMessage = postMessage;
895 customPostMessage = WorkerFacade.add("path/to/thisworker.js", nameOfWorkerFunction);