factory/v2012/script.js
author Eugen Sawin <sawine@me73.com>
Sun, 08 Jan 2012 00:59:35 +0100
changeset 96 09f399025fdc
parent 92 290ad5d7652b
child 99 a0efd850d1dd
permissions -rw-r--r--
Content improvements.
     1 var QUOTES_NUMBER = 39;
     2 var SERVER = "http://" + window.location.hostname + ":" + window.location.port;
     3 var simulation;
     4 var gameoflife;
     5 
     6 $(document).ready(function() {   
     7     simulation = new Simulation(document.getElementById("sim"), 
     8                                 670, 50, 6, green, background);  
     9     var image = new Image();
    10     image.onload = init_logo;
    11     image.src = "images/logobase.png";
    12     $("#logo").click(handle_click);   
    13     $("#logo").hover(function(event) {
    14         $(this).css("cursor", "pointer");        
    15     }, function() {
    16         $(this).css("cursor", "auto");
    17     });
    18     $("#logo").mousemove(function(event) { handle_hover(event); });
    19     $("#logo").mouseout(function(event) { handle_mouse_out(event); });
    20     $("#sim").mousemove(function(event) { simulation.mouse_moved(mouse_pos(event, "#sim")); });
    21     var onEachFrame;
    22     if (window.webkitRequestAnimationFrame) {
    23         onEachFrame = function(cb) {
    24             var _cb = function() { cb(); webkitRequestAnimationFrame(_cb); }
    25             _cb();
    26         };
    27     } else if (window.mozRequestAnimationFrame) {
    28         onEachFrame = function(cb) {
    29             var _cb = function() { cb(); mozRequestAnimationFrame(_cb); }
    30             _cb();
    31         };
    32     } else {
    33         onEachFrame = function(cb) {
    34             setInterval(cb, 1000 / 30);
    35         }
    36     }    
    37     window.onEachFrame = onEachFrame;   
    38     window.onEachFrame(update);  
    39     var pos = document.location.href.lastIndexOf("/") + 1; 
    40     var page = document.location.href.substr(pos);
    41     if (page == "mandelbrot.html") {
    42         draw(0, 0, 0, 0, 0);
    43     } else if (page == "" || page == "index.html") {
    44         init_gameoflife("ME73");
    45     } else if (page == "gameoflife.html") {
    46         init_gameoflife("");
    47     }
    48 });
    49 
    50 $(document).keypress(function(event) {
    51     if (event.which == 13) {      
    52 	event.preventDefault();
    53         update_logo();	    
    54     }
    55 });
    56 
    57 var menu_width = 670;
    58 var menu_height = 100;
    59 var menu_splits = new Array(180, 350, 505);
    60 
    61 var click_events = new Array();
    62 click_events["logo"] = new Array();
    63 click_events["logo"][0] = new Object();
    64 click_events["logo"][0]["min_x"] = 0;
    65 click_events["logo"][0]["max_x"] = menu_splits[0];
    66 click_events["logo"][0]["min_y"] = 0;
    67 click_events["logo"][0]["max_y"] = menu_height;
    68 click_events["logo"][0]["func"] = switch_page;
    69 click_events["logo"][0]["args"] = new Array("personalwork.html");
    70 click_events["logo"][1] = new Object();
    71 click_events["logo"][1]["min_x"] = menu_splits[0] + 1;
    72 click_events["logo"][1]["max_x"] = menu_splits[1];
    73 click_events["logo"][1]["min_y"] = 0;
    74 click_events["logo"][1]["max_y"] = menu_height;
    75 click_events["logo"][1]["func"] = switch_page;
    76 click_events["logo"][1]["args"] = new Array("howiwork.html");
    77 click_events["logo"][2] = new Object();
    78 click_events["logo"][2]["min_x"] = menu_splits[1] + 1;
    79 click_events["logo"][2]["max_x"] = menu_splits[2];
    80 click_events["logo"][2]["min_y"] = 0;
    81 click_events["logo"][2]["max_y"] = menu_height;
    82 click_events["logo"][2]["func"] = switch_page;
    83 click_events["logo"][2]["args"] = new Array("books.html");
    84 click_events["logo"][3] = new Object();
    85 click_events["logo"][3]["min_x"] = menu_splits[2] + 1;
    86 click_events["logo"][3]["max_x"] = menu_width - 1;
    87 click_events["logo"][3]["min_y"] = 0;
    88 click_events["logo"][3]["max_y"] = menu_height;
    89 click_events["logo"][3]["func"] = switch_page;
    90 click_events["logo"][3]["args"] = new Array("links.html", "linksend.html");
    91 
    92 function mouse_pos(event, id) { 
    93     var offset = $(id).offset();   
    94     return new Array(event.pageX - offset.left, 
    95                      event.pageY - offset.top);
    96 }
    97 
    98 function handle_click(event) {
    99     var xy = mouse_pos(event, "#logo");
   100     var x = xy[0];
   101     var y = xy[1];
   102     for (var i in click_events[event.target.id]) {
   103         var ces = click_events[event.target.id][i];
   104         if (ces && x >= ces["min_x"] && x <= ces["max_x"]
   105             && y >= ces["min_y"] && y <= ces["max_y"]) {    
   106             ces["func"](event.target.id, ces);
   107             last_colours[0] = black;
   108             break;
   109         }
   110     }
   111 }
   112 
   113 function handle_hover(event) {
   114     var xy = mouse_pos(event, "#logo");
   115     var x = xy[0];
   116     var y = xy[1];
   117     for (var i in click_events[event.target.id]) {
   118         var ces = click_events[event.target.id][i];
   119         if (ces && x >= ces["min_x"] && x <= ces["max_x"]
   120             && y >= ces["min_y"] && y <= ces["max_y"]) {    
   121             highlight_menu(event.target.id, ces);
   122             break;
   123         }
   124     }
   125 }
   126 
   127 function handle_mouse_out(event) {
   128     highlight_menu(event.target.id, null);
   129 }
   130 
   131 function switch_page(id, params) {
   132     var page = params["args"][0];
   133     $("body").load(page);
   134     document.location.href = page;    
   135 }
   136 
   137 var last_highlight;
   138 var last_colours = new Array();
   139 
   140 function highlight_menu(id, p) {
   141     if (last_highlight == p) {
   142         return;
   143     }
   144     var canvas = document.getElementById("logo");
   145     var context = canvas.getContext("2d");    
   146     var image = context.getImageData(0, 0, menu_width, menu_height);
   147     if (last_highlight && last_colours && last_colours[0] && last_colours[1]) {        
   148         page = last_highlight["args"][0]; 
   149         min_x = last_highlight["min_x"];
   150         max_x = last_highlight["max_x"];
   151         min_y = last_highlight["min_y"];
   152         max_y = last_highlight["max_y"];
   153         colour_area(image, min_x + 10, max_x - 10, 0, 60, 
   154                     last_colours[0]);
   155         colour_area(image, min_x + 10, max_x - 10, 60, max_y - 10, 
   156                     last_colours[1]);
   157     }
   158     if (p) {    
   159         var page = p["args"][0]; 
   160         var min_x = p["min_x"];
   161         var max_x = p["max_x"];
   162         var min_y = p["min_y"];
   163         var max_y = p["max_y"];       
   164         last_colours[0] = colour_area(image, min_x + 10, max_x - 10, 0, 60, 
   165                                       orange);
   166         last_colours[1] = colour_area(image, min_x + 10, max_x - 10, 60, max_y - 10, 
   167                                       white);      
   168     }
   169     
   170     context.putImageData(image, 0, 0);
   171     last_highlight = p;
   172 }
   173 
   174 function colour_area(image, min_x, max_x, min_y, max_y, colour) {   
   175     var pixels = image.data;
   176     var old_colour;
   177     for (var y = min_y; y <= max_y; y += 1) {
   178         for (var x = min_x; x <= max_x; x += 1) {
   179             var pix_colour = getPixel(image, x, y);
   180             if (pix_colour.a > 0) {
   181                 colour.a = pix_colour.a;               
   182                 setPixel(image, x, y, colour); 
   183                 if (pix_colour.a == 255) {
   184                     old_colour = pix_colour;
   185                 }
   186             }
   187         }
   188     }
   189     return old_colour;
   190 }
   191 
   192 function init_logo(event) {
   193     var canvas = document.getElementById("logo");
   194     var context = canvas.getContext("2d");    
   195     canvas.width = menu_width;
   196     canvas.height = menu_height;
   197     context.drawImage(event.target, 0, 0);
   198     var image = context.getImageData(0, 0, menu_width, menu_height);    
   199     for (var i in click_events["logo"]) {
   200         var p = click_events["logo"][i]; 
   201         var min_x = p["min_x"];
   202         var max_x = p["max_x"];
   203         var min_y = p["min_y"];
   204         var max_y = p["max_y"];
   205         var pos = document.location.href.lastIndexOf("/") + 1; 
   206         var page = document.location.href.substr(pos);        
   207         for (var j in p["args"]) {
   208             if (page == p["args"][j]) {         
   209                 colour_area(image, min_x, max_x, 0, 60, black);
   210                 colour_area(image, min_x, max_x, 60, max_y, white);
   211                 break;
   212             }
   213             else {
   214                 colour_area(image, min_x, max_x, 0, 60, white);
   215                 colour_area(image, min_x, max_x, 60, max_y,  orange);  
   216             }
   217         }       
   218     } 
   219     context.putImageData(image, 0, 0);      
   220     // context.fillStyle = green.str();
   221     // console.log((found["max_x"] - found["min_x"]) / 2 + found["min_x"] - 2);
   222     // context.fillRect((found["max_x"]-found["min_x"])/2+found["min_x"]-1, 95, 2, 5);  
   223     draw_menu_lines();   
   224 }
   225 
   226 function draw_menu_lines() {
   227     var canvas = document.getElementById("logo");
   228     var context = canvas.getContext("2d");  
   229     var image = context.getImageData(0, 0, menu_width, menu_height);
   230     var pixels = image.data;
   231     context.lineCap = "round";
   232     context.lineWidth = 1;
   233     var colour1a = new Colour(0, 0, 0, 0.1);
   234     context.beginPath();   
   235     context.moveTo(0, menu_height - 1);
   236     context.lineTo(menu_width - 1, menu_height - 1);   
   237     context.closePath();  
   238     context.strokeStyle = colour1a.str();
   239     context.stroke(); 
   240     var colour1e = new Colour(0, 0, 0, 0.05);  
   241     context.beginPath();   
   242     context.moveTo(70, menu_height - 1);
   243     context.lineTo(menu_width - 71, menu_height - 1);   
   244     context.closePath();  
   245     context.strokeStyle = colour1e.str();
   246     context.stroke();  
   247     var colour1b = new Colour(0, 0, 0, 0.05);  
   248     context.beginPath();   
   249     context.moveTo(50, menu_height - 1);
   250     context.lineTo(menu_width - 51, menu_height - 1);   
   251     context.closePath();  
   252     context.strokeStyle = colour1b.str();
   253     context.stroke();
   254     var colour1c = new Colour(0, 0, 0, 0.05);  
   255     context.beginPath();   
   256     context.moveTo(25, menu_height - 1);
   257     context.lineTo(menu_width - 26, menu_height - 1);   
   258     context.closePath();  
   259     context.strokeStyle = colour1c.str();
   260     context.stroke();
   261     var colour1d = new Colour(0, 0, 0, 0.05);  
   262     context.beginPath();   
   263     context.moveTo(10, menu_height - 1);
   264     context.lineTo(menu_width - 11, menu_height - 1);   
   265     context.closePath();  
   266     context.strokeStyle = colour1d.str();
   267     context.stroke();  
   268     
   269     var colour2 = new Colour(0, 0, 0, 0.2);
   270     context.beginPath();  
   271     context.moveTo(menu_splits[0], 0); 
   272     context.lineTo(menu_splits[0], menu_height - 1);
   273     context.moveTo(menu_splits[1], 0);
   274     context.lineTo(menu_splits[1], menu_height - 1);
   275     context.moveTo(menu_splits[2], 0);
   276     context.lineTo(menu_splits[2], menu_height - 1);
   277     context.closePath();
   278     context.strokeStyle = colour2.str();
   279     context.stroke();
   280 
   281     context.clearRect(menu_splits[0] - 1, menu_height - 1, 2, 2);
   282     context.clearRect(menu_splits[1] - 1, menu_height - 1, 2, 2);
   283     context.clearRect(menu_splits[2] - 1, menu_height - 1, 2, 2);
   284 
   285     context.clearRect(menu_splits[0] - 1, menu_height - 2, 1, 1);
   286     context.clearRect(menu_splits[1] - 1, menu_height - 2, 1, 1);
   287     context.clearRect(menu_splits[2] - 1, menu_height - 2, 1, 1);
   288 }
   289 
   290 function clearMenuLines() {
   291     var canvas = document.getElementById("logo");
   292     var context = canvas.getContext("2d");  
   293     var image = context.getImageData(0, 0, menu_width, menu_height);
   294     var pixels = image.data;
   295     context.clearRect(0, menu_height - 2, menu_width - 1, 2);
   296     context.clearRect(menu_splits[0] - 1, 0, 2, menu_height - 1);
   297     context.clearRect(menu_splits[1] - 1, 0, 2, menu_height - 1);
   298     context.clearRect(menu_splits[2] - 1, 0, 2, menu_height - 1);
   299 }
   300 
   301 function draw_sim_lines() {
   302     var w = 670;
   303     var h = 50;
   304     var canvas = document.getElementById("sim");
   305     var context = canvas.getContext("2d");  
   306     var image = context.getImageData(0, 0, w, h);
   307     var pixels = image.data;
   308     context.lineCap = "round";
   309     context.lineWidth = 1;
   310     var colour1a = new Colour(0, 0, 0, 0.1);
   311     context.beginPath();   
   312     context.moveTo(0, h - 1);
   313     context.lineTo(w - 1, h - 1);   
   314     context.closePath();  
   315     context.strokeStyle = colour1a.str();
   316     context.stroke(); 
   317     var colour1e = new Colour(0, 0, 0, 0.05);  
   318     context.beginPath();   
   319     context.moveTo(70, h - 1);
   320     context.lineTo(w - 71, h - 1);   
   321     context.closePath();  
   322     context.strokeStyle = colour1e.str();
   323     context.stroke();  
   324     var colour1b = new Colour(0, 0, 0, 0.05);  
   325     context.beginPath();   
   326     context.moveTo(50, h - 1);
   327     context.lineTo(w - 51, h - 1);   
   328     context.closePath();  
   329     context.strokeStyle = colour1b.str();
   330     context.stroke();
   331     var colour1c = new Colour(0, 0, 0, 0.05);  
   332     context.beginPath();   
   333     context.moveTo(25, h - 1);
   334     context.lineTo(w - 26, h - 1);   
   335     context.closePath();  
   336     context.strokeStyle = colour1c.str();
   337     context.stroke();
   338     var colour1d = new Colour(0, 0, 0, 0.05);  
   339     context.beginPath();   
   340     context.moveTo(10, h - 1);
   341     context.lineTo(w - 11, h - 1);   
   342     context.closePath();  
   343     context.strokeStyle = colour1d.str();
   344     context.stroke();   
   345 }
   346 
   347 function update_logo() {
   348     var canvas = document.getElementById("logo");
   349     var context = canvas.getContext("2d");  
   350     var image = context.getImageData(0, 0, menu_width, menu_height);
   351     var pixels = image.data;
   352     var white = new Colour(255, 255, 255);
   353     for (var y = 0; y < menu_height; y += 1) {
   354         for (var x = 0; x < menu_width; x += 1) {
   355             var pix_colour = getPixel(image, x, y);
   356             if (pix_colour.a > 0) {
   357                 setPixel(image, x, y, new Colour(90, 215, 21, pix_colour.a));
   358             }
   359         }
   360     }   
   361     context.putImageData(image, 0, 0);
   362 }
   363 
   364 var char_map = new Array();
   365 char_map["A"] = new Array(new Array(0, 4), new Array(1, 3),
   366                           new Array(2, 2), new Array(3, 1),
   367                           new Array(4, 0), new Array(5, 1),
   368                           new Array(6, 2), new Array(7, 3),
   369                           new Array(8, 4), new Array(2, 3),
   370                           new Array(3, 3), new Array(4, 3),
   371                           new Array(5, 3), new Array(6, 3));
   372 char_map["M"] = new Array(new Array(0, 4), new Array(0, 3),
   373                           new Array(0, 2), new Array(0, 1),
   374                           new Array(0, 0), new Array(0, 5),
   375                           new Array(5, 4), new Array(5, 3),
   376                           new Array(5, 2), new Array(5, 1),
   377                           new Array(5, 0), new Array(5, 5),
   378                           new Array(1, 1), new Array(2, 2), 
   379                           new Array(4, 2), new Array(5, 1),
   380                           new Array(3, 3));
   381 char_map["E"] = new Array(new Array(0, 4), new Array(0, 3),
   382                           new Array(0, 2), new Array(0, 1),
   383                           new Array(0, 0), new Array(0, 5),
   384                           new Array(1, 0), new Array(2, 0),
   385                           new Array(3, 0),
   386                           new Array(1, 3), new Array(2, 3),                       
   387                           new Array(1, 5), new Array(2, 5),
   388                           new Array(3, 5))
   389 char_map["7"] = new Array(new Array(0, 0), new Array(1, 0),
   390                           new Array(2, 0),
   391                           new Array(0, 5), new Array(0, 4),
   392                           new Array(1, 3), new Array(2, 2));
   393 char_map["3"] = new Array(new Array(2, 4), new Array(2, 3),
   394                           new Array(2, 2), new Array(2, 1),
   395                           new Array(0, 0), new Array(0, 5),
   396                           new Array(1, 0), new Array(2, 0),                         
   397                           new Array(1, 3), new Array(2, 3),                          
   398                           new Array(1, 5), new Array(2, 5))
   399 
   400 function init_gameoflife(text) {
   401     var canvas = document.getElementById("gameoflife");
   402     var cell_size = 16;
   403     if (canvas) {
   404         gameoflife = new Simulation(canvas, 670, 670, cell_size,
   405                                     green, black);
   406         $("#gameoflife").mousemove(function(event) { 
   407             gameoflife.mouse_moved(mouse_pos(event, "#gameoflife")); 
   408         });       
   409         var offset = new Array(13, 16);
   410         for (var c in text) {            
   411             var w = 0;
   412             for (p in char_map[text[c]]) {
   413                 var x = char_map[text[c]][p][0];
   414                 var y = char_map[text[c]][p][1];
   415                 w = Math.max(w, x);
   416                 var pos = new Array((x + offset[0]) * cell_size, 
   417                                     (y + offset[1]) * cell_size);
   418                 gameoflife.activate_cell(pos);
   419             }            
   420             offset[0] += w + 2;
   421         }       
   422     }    
   423 }
   424 
   425 function Colour(r, g, b, a) {
   426     this.r = r;
   427     this.g = g;
   428     this.b = b;
   429     this.a = a == undefined ? 255 : a;
   430 }
   431 Colour.prototype.equals = function(rhs) {
   432     for (p in this) {
   433         if (typeof(rhs[p]) == undefined
   434            || this[p] != rhs[p]) {           
   435             return false;
   436         }
   437     }
   438     return true;
   439 }
   440 Colour.prototype.str = function() {
   441     return "rgba(" + this.r + "," + this.g + "," + this.b + "," + this.a + ")";
   442 }
   443 
   444 var white = new Colour(255, 255, 255);
   445 var black = new Colour(0, 0, 0, 255);
   446 var orange = new Colour(201, 87, 35, 255);
   447 var green = new Colour(90, 215, 21, 255);
   448 var background = new Colour(34, 34, 34, 255);
   449 
   450 function setPixel(image, x, y, colour) {
   451     var index = 4 * (x + y * image.width);
   452     image.data[index] = colour.r;
   453     image.data[index + 1] = colour.g;
   454     image.data[index + 2] = colour.b;
   455     image.data[index + 3] = colour.a;
   456 }
   457 
   458 function getPixel(image, x, y) {   
   459     var index = 4 * (x + y * image.width);
   460     var r = image.data[index];
   461     var g = image.data[index + 1];
   462     var b = image.data[index + 2];
   463     var a = image.data[index + 3];
   464     return new Colour(r, g, b, a);
   465 }
   466 
   467 function load_random_quote() {
   468     var file = "/quotes/quote" + Math.floor(Math.random() * QUOTES_NUMBER + 1) + ".html";
   469     $.ajax({url: SERVER + file,
   470             success: write_quote});
   471 }
   472 
   473 function write_quote(data, status, xhr) {   
   474     $("#random_quote").html(data);
   475 }
   476 
   477 function load_footer()
   478 {
   479 	var file = "/footer.html";
   480 	var currentFile = self.location.hostname + self.location.pathname;		
   481 	var request = http_request_object();
   482 	var url  = "http://" + self.location.hostname + file;	
   483 	request.open("GET", url, false);
   484 	request.setRequestHeader("User-Agent", navigator.userAgent);
   485 	request.send(null)
   486 	// if (oRequest.status == 200) alert(oRequest.responseText);
   487 	// else alert("Error executing XMLHttpRequest call!");	
   488 	//document.write(url);
   489 	//document.write(request.responseText);
   490     document.getElementById('footer').innerHTML = request.responseText;
   491 }
   492 
   493 
   494 
   495 // Mandelbrot functions
   496 function Complex(real, imag) 
   497 {
   498 	this.real = real;
   499 	this.imag = imag;
   500 }
   501 
   502 var MIN_C = new Complex(-2.2, -1.4);
   503 var MAX_C = new Complex(1.0, 1.4);
   504 var min_c = MIN_C;
   505 var max_c = MAX_C;
   506 var MIN_ITER = 100;
   507 var max_iter = MIN_ITER;
   508 var zoom = 1.0;
   509 var resolution = 3;
   510 var bailout = 4.0;
   511 
   512 function Result(z, iter) 
   513 {
   514 	this.z = z;
   515 	this.iter = iter;
   516 }
   517 
   518 function complex_quad(c)
   519 {
   520 	return new Complex(Math.pow(c.real, 2) - Math.pow(c.imag, 2), 
   521 		2.0 * c.real * c.imag);
   522 }
   523 
   524 function complex_quad_value(c)
   525 {
   526 	return Math.pow(c.real, 2) + Math.pow(c.imag, 2);
   527 }
   528 
   529 function complex_add(c1, c2)
   530 {
   531 	return new Complex(c1.real + c2.real, c1.imag + c2.imag);
   532 }
   533 
   534 function complex_equal(c1, c2)
   535 {	
   536 	return (c1.real == c2.real) && (c1.imag == c2.imag);
   537 }
   538 
   539 function iterate(z, c) 
   540 {
   541 	z_quad = complex_quad(z);
   542 	return new Complex(z_quad.real + c.real, z_quad.imag + c.imag);
   543 }
   544 
   545 function test(c, max_iter) 
   546 {
   547 	var iter = 0;
   548 	var z = new Complex(0.0, 0.0);
   549 	var last_z = new Complex(-1.0, 0.0);
   550 	var quad_z = complex_quad_value(z);
   551 	
   552 	while (iter < max_iter
   553 		&& !complex_equal(z, last_z)
   554 		&& quad_z <= bailout)
   555 	{
   556 		last_z = z;
   557 		z = iterate(z, c);
   558 		quad_z = complex_quad_value(z);
   559 		iter++;
   560 	}
   561 	return new Result(quad_z, iter);
   562 }
   563 
   564 function draw(diter, dx, dy, dz, dres)
   565 {  
   566 	var canvas = document.getElementById('mandelbrot'); 
   567 	
   568 	if (canvas.getContext)
   569 	{  
   570 		zoom += dz;
   571 		var ctx = canvas.getContext('2d');
   572 
   573 		if (dres != 0)
   574 		{		
   575 			resolution = Math.max(1, resolution + dres);
   576 		}
   577 
   578 		if (diter != 0)
   579 		{
   580 			max_iter = Math.max(MIN_ITER, max_iter + diter);
   581 		}
   582 		
   583 		var red = "rgb(255, 0, 0)";
   584 		var white = "rgb(255, 255, 255)";
   585 		var width = canvas.width;
   586 		var height = canvas.height;
   587 		var dim = Math.max(width, height);
   588 		var dim_ratio = Math.round(width / height);	
   589 		var diff_c = new Complex(max_c.real - min_c.real,
   590 			max_c.imag - min_c.imag);
   591 		dx_min = diff_c.real / 100 * (dx + dz);
   592 		dx_max = diff_c.real / 100 * (dx - dz);
   593 
   594 		dy_min = diff_c.imag / 100 * (dy + dz);
   595 		dy_max = diff_c.imag / 100 * (dy - dz);
   596 
   597 		var min_inc = new Complex(dx_min * dim_ratio / 2.0, dy_min);
   598 		var max_inc = new Complex(dx_max * dim_ratio / 2.0, dy_max);
   599 		min_c = complex_add(min_c, min_inc);
   600 		max_c = complex_add(max_c, max_inc);
   601 		diff_c = new Complex(max_c.real - min_c.real,
   602 			max_c.imag - min_c.imag);
   603 		
   604 		for (var y = 0; y < height; y += resolution) 
   605 		{
   606 			for (var x = 0; x < width; x += resolution) 
   607 			{    			
   608 				var c = new Complex(min_c.real + diff_c.real / dim * x, 
   609 					min_c.imag + diff_c.imag / dim * y);  	
   610 			 	var result = test(c, max_iter);	
   611 		 		var r = Math.min(255, Math.pow(Math.max(0, 
   612 		 			(result.iter - max_iter / 20.0)), 2));
   613 				var g = Math.min(255, Math.pow(Math.max(0, 
   614 					(result.iter - max_iter / 25.0)), 2));			
   615 		 		var b = Math.min(255, Math.pow(Math.max(0, 
   616 					(result.iter - max_iter / 20.0)), 2));
   617 		 		var colour = "rgb(" + r + "," + g + "," + b + ")";
   618 		 		ctx.fillStyle = colour; 
   619 				ctx.fillRect(x, y, resolution, resolution);			
   620 			}
   621   		}
   622 	}  
   623 } 
   624 
   625 function getEventOffsetX(evt)
   626 {
   627 	if (evt.offsetX != null)
   628 		return evt.offsetX;
   629  
   630     var obj = evt.target || evt.srcElement;
   631    	setPageTopLeft(obj);
   632     return (evt.clientX - obj.pageLeft);
   633 }
   634 
   635 function getEventOffsetY(evt)
   636 {
   637 	if (evt.offsetY != null)
   638 		return evt.offsetY;
   639  
   640     var obj = evt.target || evt.srcElement;
   641    	setPageTopLeft(obj);
   642     return (evt.clientY - obj.pageTop);
   643 }
   644  
   645 function setPageTopLeft( o )
   646 {
   647     var top = 0,
   648     left = 0,
   649     obj = o;
   650  
   651     while (o.offsetParent)
   652      {
   653          left += o.offsetLeft ;
   654          top += o.offsetTop ;
   655          o = o.offsetParent ;
   656     };
   657  
   658     obj.pageTop = top;
   659     obj.pageLeft = left; 
   660 }
   661  
   662 function draw2(evt) {
   663     var iter = 0;
   664     var res = 0;
   665     var x = (getEventOffsetX(evt) - 335) / 167.5;
   666     var y = (getEventOffsetY(evt) - 140) / 70;
   667     var z = 0;
   668     draw(iter, x, y, z, res);
   669 }
   670 
   671 function update() {
   672     simulation.update();
   673     simulation.draw();
   674     if (gameoflife) {
   675         gameoflife.update();
   676         gameoflife.draw();
   677     }
   678 }
   679 
   680 function Grid(width, height, cell_size) {
   681     this.width = parseInt(width / cell_size + 0.5);
   682     this.height = parseInt(height / cell_size + 0.5);
   683     this.canvas_width = width;
   684     this.canvas_height = height;
   685     this.cell_size = cell_size;  
   686     this.cells = new Array();
   687     for (var y = 0; y < this.height; ++y) { 
   688         this.cells[y] = new Array();
   689         for (var x = 0; x < this.width; ++x) {
   690             this.cells[y][x] = new Cell(x, y, 0, this);
   691         }
   692     }
   693 }
   694 Grid.prototype.cell = function(x, y) {   
   695     return this.cells[y][x];
   696 }
   697 Grid.prototype.pick_cell = function(x, y) {
   698     var lx = parseInt(x / this.cell_size - 0.5);
   699     var ly = parseInt(y / this.cell_size - 0.5);  
   700     return this.cells[ly][lx];
   701 }
   702 
   703 function Cell(x, y, value, grid) {
   704     this.x = x;
   705     this.y = y;  
   706     this.canvas_x = x * grid.cell_size;
   707     this.canvas_y = y * grid.cell_size;
   708     this.value = value;
   709     this.grid = grid;
   710     this._neighbours = new Array();
   711     this.last_mod = 0;
   712 }
   713 Cell.prototype.hash = function() {
   714     return this.x + ", " + this.y;
   715 }
   716 Cell.prototype.set_value = function(value) {
   717     this.value = value;
   718     this.last_mod = $.now();
   719 }
   720 Cell.prototype.neighbours = function() {
   721     if (this._neighbours.length) {
   722         return this._neighbours;
   723     }
   724     if (this.x > 0) {
   725         this._neighbours.push(this.grid.cell(this.x-1, this.y));
   726         if (this.y > 0) {
   727             this._neighbours.push(this.grid.cell(this.x-1, this.y-1));
   728             this._neighbours.push(this.grid.cell(this.x, this.y-1));
   729         }
   730         if (this.y + 1 < this.grid.height) {
   731             this._neighbours.push(this.grid.cell(this.x-1, this.y+1));
   732         }
   733     }   
   734     if (this.x + 1 < this.grid.width) {
   735         this._neighbours.push(this.grid.cell(this.x+1, this.y));
   736         if (this.y + 1 < this.grid.height) {
   737             this._neighbours.push(this.grid.cell(this.x+1, this.y+1));
   738             this._neighbours.push(this.grid.cell(this.x, this.y+1));
   739         }
   740         if (this.y > 0) {
   741             this._neighbours.push(this.grid.cell(this.x+1, this.y-1));
   742         }
   743     }
   744     return this._neighbours;
   745 }
   746 Cell.prototype.density = function() {
   747     var d = 0;
   748     var neighbours = this.neighbours();
   749     for (var n in neighbours) {
   750         d += neighbours[n].value;
   751     }
   752     return d;
   753 }
   754 
   755 function Simulation(canvas, w, h, cell_size, life_colour, dead_colour) {
   756     this.last_update = $.now() + 3000;
   757     this.last_draw = 0;
   758     this.last_mouse_moved = 0;
   759     this.redraw = new Array();   
   760     this.canvas = canvas;
   761     this.canvas.width = w;
   762     this.canvas.height = h;
   763     this.context = canvas.getContext("2d");    
   764     this.pos_queue = new Array();
   765     this.cell_queue = new Array();  
   766     this.cell_size = cell_size;
   767     this.life_colour = life_colour;
   768     this.dead_colour = dead_colour;
   769     this.grid = new Grid(this.canvas.width, this.canvas.height, cell_size);
   770     draw_sim_lines();
   771 }
   772 Simulation.prototype.draw = function() {
   773     var now = $.now();
   774     if (this.redraw.length) {
   775         var cell = this.redraw[0];
   776         this.redraw.shift();
   777         this.context.fillStyle = cell.value == 1 ? 
   778             this.life_colour.str() : this.dead_colour.str();
   779         this.context.fillRect(cell.canvas_x, cell.canvas_y, 
   780                               this.grid.cell_size, this.grid.cell_size);
   781         this.last_draw = $.now();
   782     }
   783 }
   784 Simulation.prototype.update = function() {
   785     var now = $.now();
   786     while (this.pos_queue.length) {
   787         var pos = this.pos_queue.pop();       
   788         if (pos[0] < this.canvas.width
   789             && pos[1] < this.canvas.height) {
   790             var cell = this.grid.pick_cell(pos[0], pos[1]);
   791             cell.set_value(1);
   792             this.cell_queue.push(cell);
   793             this.cell_queue.concat(cell.neighbours()); 
   794             this.redraw.unshift(cell);          
   795         }
   796     }
   797     if (this.last_update + 1000 > now) {
   798         return;
   799     }
   800     var changed = new Array();
   801     var next_cell_queue = new Array();
   802     while (this.cell_queue.length) {
   803         var cell = this.cell_queue.pop();       
   804         if (changed[cell.hash()]) {           
   805             continue;
   806         }
   807         var d = cell.density();
   808         if (d == 3 && cell.value == 0) {           
   809             changed[cell.hash()] = cell;            
   810             next_cell_queue = next_cell_queue.concat(cell.neighbours());               
   811         } else if (cell.value == 1) {
   812             if (d < 2 || d > 3) {              
   813                 changed[cell.hash()] = cell;                
   814                 next_cell_queue = next_cell_queue.concat(cell.neighbours());               
   815             }
   816         }       
   817     }
   818     for (var pos in changed) {
   819         var cell = changed[pos];      
   820         cell.set_value(1 - cell.value);
   821         this.redraw.push(cell);
   822     }
   823     this.cell_queue = next_cell_queue;
   824     this.last_update = now;  
   825 }
   826 Simulation.prototype.activate_cell = function(pos) {
   827     this.pos_queue.push(pos);   
   828 }
   829 Simulation.prototype.mouse_moved = function(pos) {
   830     var now = $.now();    
   831     if (this.last_mouse_moved + 50 < now) {       
   832         this.pos_queue.push(pos);      
   833         this.last_mouse_moved = now;       
   834     }
   835 }
   836 
   837