<?php

if (@$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
  /*
  create table breadcrumbs (
    id int unsigned primary key auto_increment,
    type ENUM('click', 'move'),
    url varchar(256),
    x int unsigned not null default 0,
    y int unsigned not null default 0 ),
    count int unsigned not null default 0,
    unique (type, url, x, y
  );
  */

  require_once(dirname(__FILE__) . '/db-test.inc');

  header('Content-Type: application/json');

  if ($_POST['action'] == 'refresh') {
    $max = 0;
    if ($sth = DB::query("SELECT MAX(`count`) FROM breadcrumbs"))
      $max = $sth->fetchColumn();

    $data['plots'] = [];

    $rows = DB::get_rows('breadcrumbs', ['id', 'type', 'x', 'y', 'count'], ['where' => ['id' => ['>' => $_POST['lastid']]], 'order' => 'id']);

    foreach ($rows as list($id, $type, $x, $y, $count)) {
      $data['lastid'] = $id;

      $percent = round($count / $max * 100);
      
      if ($type == 'click') {
        $alpha = 160;
        $percent = min(100, $percent * 10);
      }
      else
        $alpha = 80;

      if ($percent >= 90)
        $rgb = [255, 0, 0];
      else if ($percent >= 80)
        $rgb = [255, 128, 0];
      else if ($percent >= 70)
        $rgb = [255, 255, 0];
      else if ($percent >= 60)
        $rgb = [128, 255, 0];
      else if ($percent >= 50)
        $rgb = [0, 255, 0];
      else if ($percent >= 40)
        $rgb = [0, 255, 128];
      else if ($percent >= 30)
        $rgb = [0, 255, 255];
      else if ($percent >= 20)
        $rgb = [0, 128, 255];
      else if ($percent >= 10)
        $rgb = [0, 0, 255];
      else
        $rgb = [0, 0, 128];

      $data['plots'][] = [
        'type' => $type,
        'r' => $rgb[0],
        'g' => $rgb[1],
        'b' => $rgb[2],
        'a' => $alpha,
        'x' => $x,
        'y' => $y,
      ];
    }

    die(json_encode($data));
  }

  if (in_array($_POST['type'], ['click', 'move'])) {
    $bind = [
      ':type'   => $_POST['type'],
      ':url'   => $_POST['url'],
      ':x'     => $_POST['x'],
      ':y'     => $_POST['y'],
      ':count' => 1,
    ];

    DB::query("INSERT INTO `breadcrumbs` (type, url, x, y, `count`) VALUES (:type, :url, :x, :y, :count) ON DUPLICATE KEY UPDATE `count` = `count` + 1", $bind);
  }

  die(json_encode([]));
}

?>
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="canonical" href="http://rommelsantor.com"/>
<link rel="icon" type="image/ico" href="http://rommelsantor.com/favicon.ico">
<link rel="me" type="text/html" href="http://www.google.com/profiles/lucky760"/>
<link rel="me" type="text/html" href="http://lucky760.teevirus.com"/>
<link rel="me" type="text/html" href="http://lucky760.videosift.com"/>
<link rel="me" type="text/html" href="http://blog.videosift.com/lucky760"/>
<title>Rommel Santor | Back-end / Front-End / Full-Stack Web Developer</title>
<style type="text/css">
  * { margin: 0; padding: 0; }
  body { background: /*#ffd*/ #efefef; }
  a { text-decoration: none; font-weight: bold; color: #03f; }
  a img { border: 0; }
  .body { padding: 15px; margin: 15px 30px; background: #fff; border: 1px solid #c0c0c0; text-align: justify; /*width: 920px;*/ margin: 30px 5%/*auto*/; min-width: 320px; }
  h1 { /*border-bottom: 1px solid #ccc;*/ font-family: georgia,"times new roman",serif; font-size: 27px; font-variant: small-caps; padding-bottom: 10px; position: relative; }
  h2 { margin-left: 10px; font-family: helvetica,arial,sans-serif; font-size: 14px; font-weight: 400; letter-spacing: 0.05em; margin-top: 28px; text-transform: uppercase; }
  hr { clear: both; }
  p, ul { margin: 10px; padding-left: 1em; font-family: helvetica,arial,sans-serif; line-height: 22px; font-size: 12px; }
  p b { font-size: 14px; }
  .st { display: inline-block; font-size: 16px; margin: 10px 0; font-weight: normal; letter-spacing: 0.07em; position: absolute; bottom: 3px; right: 0; }
  ul {
    list-style: inside;
  }
  ul p {
    margin: 5px 0 15px;
    padding-left: 1em;
  }

  @media (max-width: 469px) {
    .body {
      margin: 5px;
      min-width: 260px;
    }
    h1 {
      font-size: 24px;
      text-align: center;
    }
    .st {
      display: block;
      position: static;
    }
  }
</style>
</head>
<body>
<div class="body">
<h1>Rommel Santor <span class="st">Back-end / Front-End / Full-Stack Web Developer</span></h1>
<hr/>
<h2>About Me</h2>
<p>
  I've been fascinated with creating things since childhood and once I got my hands on my
  first computer I started teaching myself computer programming and just ran with it.
  My career, passion, and past-time is designing and implementing smart software, but since
  I became a father of two amazing little boys, they are the light of my life and the reason
  my working hours have shrunken significantly.
</p>
<ul>
  <li>
    <a href="http://linkedin.com/in/rommelsantor" target="_blank">LinkedIn</a>
  </li>
  <li>
    <a href="http://github.com/rommelsantor" target="_blank">GitHub</a>
  </li>
  <li>
    <a href="http://codepen.io/rommelsantor" target="_blank">CodePen</a>
  </li>
</ul>
<h2>Web Software Engineer</h2>
<p>
  My expertise is with all aspects of Web software development with heavy emphasis on both
  back-end to front-end, usually from scratch.
</p>
<h2>Coding and Writing</h2>
<p>
  In the past I would sometimes write about interesting software experiences in my <a href="/clog">coding log</a>.
  You may also find useful the <a href="/jquery">jQuery plugins</a> I have written.
</p>
<h2>Recent and Notable Projects</h2>
<ul>
  <?php /*
  <li>
    <a href="http://dontworryboutme.com" target="_blank" title="&quot;Don't Worry 'Bout Me&quot; &mdash;Caelan Biehn">DontWorryBoutMe.com</a>
    <p>
      Simple, fun web page that automatically pulls content from Instagram and Twitter.
    </p>
  </li>
  */ ?>

  <li>
    <a href="http://hyperloop.rommelsantor.com" target="_blank" title="edWEcate">Hyperloop-One</a>
    <p>
      I implemented using VueJS for Hyperloop-One an offline micro-site to be run with specific hardware
      projecting onto an 80"x60" tabletop surface turned into a touch-interactive interface. (So in browser
      it is best viewed at 800x600.) This was intended to be part of a presentation in Dubai, where
      the first production Hyperloop route may bring Elon Musk's vision to life.
    </p>
  </li>

  <li>
    <a href="http://11pelicanvista.com" target="_blank" title="11 Pelican Vista, Laguna Beach, CA">11 Pelican Vista</a>
    <p>
      Example media-heavy responsive property page generated by a custom CMS implemented for
      <a href="http://seevantage.com" target="_blank" title="Vantage Virtual">Vantage Virtual</a>,
      who provides luxury digital brochures including aerial video, interior/exterior photography
      and videography, and virtual reality 3D interiors and exteriors.
    </p>
  </li>

  <li>
    <a href="http://edwecate.com" target="_blank" title="edWEcate">edWEcate.com</a>
    <p>
      This is an in-progress single-page application that I'm building almost exclusively with AngularJS on the front-end. The site is meant
      for myself and other developers to help educate one another by sharing short, concise articles/tutorials about various software technologies.
    </p>
  </li>

  <li>
    <a href="http://lmfahs.com" target="_blank" title="LMFAHS">LMFAHS.com</a>
    <p>
      Responsive full-window video playlist player. It currently has a single, manual video list, but the future plan is to
      allow users to create their own custom playlists that they can share.
    </p>
  </li>

  <li>
    <a href="http://homgroup.com" target="_blank" title="H&Ocirc;M Real Estate Group">HOMGroup.com</a>
    <p>
      Luxury real estate company on the southern California coast. Public website and back-end management
      system architected from scratch. Features as-you-type MLS property search on the homepage.
    </p>
  </li>

  <li>
    <a href="http://homesandhues.com" target="_blank" title="Homes and Hues">HomesAndHues.com</a>
    <p>
      Photo-centric blog about homes, interior design, and architecture custom built to include powerful
      pop-up photo galleries that are easily authored and nicely functional.
    </p>
  </li>

  <li>
    <a href="http://urban-buddhi.com" target="_blank" title="Urban Buddhi Magazine">Urban-Buddhi.com</a>
    <p>
      Currently just an introductory holding page, a rather complex task was implementing
      self-writing handwritten text. It was a challenge to balance text quality
      against image file size and determining how best to actually animate the text.
    </p>
  </li>

  <li>
    <a href="http://imagehotspotter.com" target="_blank" title="WordPress Plugin for Interactive Image Maps">ImageHotSpotter.com</a>
    <p>
      WordPress plugin to easily create rich, interactive image maps where small regions of a larger image can be interacted with
      using an elegant UI. These regions can pop up an information box when clicked and while hovering with your mouse can display
      a custom HTML panel.
    </p>
  </li>

  <li>
    <a href="http://gdurl.com/" target="_blank" title="Direct Permanent Links for Google Drive">gdURL.com</a>
    <p>
      Public service to provide direct permalinks for files stored on Google Drive.
    </p>
  </li>

  <li>
    <a href="http://www.neatorama.com/" target="_blank">Neatorama.com</a>
    <p>
      3+ million monthly visitor blog required custom blogging platform built from scratch to replace WordPress and
      integrate with existing custom online store.
    </p>
  </li>

  <li>
    <a href="http://www.neatoshop.com/" target="_blank">NeatoShop.com</a>
    <p>
      Successful online store for popular blog required custom e-commerce shopping cart solution built from scratch. Includes
      affiliate program wherein third-party websites can have custom-skinned shops that are hosted and have orders fulfilled
      by the primary. Affiliate shops include: <a href="http://shop.boingboing.net" target="_blank" rel="nofollow">Boing Boing</a>,
      <a href="http://shop.fark.com" target="_blank" rel="nofollow">Fark</a>
    </p>
  </li>

  <li>
    <a href="http://videosift.com" target="_blank" title="Online Video Quality Control">VideoSift.com</a>
    <p>
      1+ million monthly visitor online video sharing website required custom CMS built from scratch to support extensive
      gamification and community-centric functionality.
    </p>
  </li>
</ul>
</div>

<div style="height:0;overflow:hidden;">
<div>
<h2>Don't Quit Your Day Job</h2>
<p>
  <b>1997 to 2010</b> I worked in the airline industry building software applications involved
  with the revenue accounting side of the business.
</p>
<p>
  <b>2010 to present</b> I have worked for a great real estate group based in Newport
  Beach, California as Director of Software Development. I spend my days engineering and developing
  from scratch all of the company's large scale web-based software systems, from their public facing
  web sites to their back-end business management system.
</p>
<h2>Freelance/Consulting</h2>
<p>
  <b>2006</b> I joined <a href="http://videosift.com" target="_blank">VideoSift.com</a> as IT
  Director and built the custom PHP-based CMS that still powers the site today. I continue working
  on software and act as system administrator on the four servers on which VideoSift resides.
  VideoSift receives approximately 1.5 million unique visitors per month.
</p>
<p>
  <b>2009</b> I build <a href="http://teevirus.com" target="_blank">TeeVirus.com</a> which was a
  very interesting community-based e-commerce site, wherein members could submit their own custom
  t-shirt designs. Other members would vote on the quality of the design, and those with the best
  ratings would make it into the store available for purchase, earning the designer a commission for
  each sale.
</p>
<p>
  <b>2009</b> I built from scratch a brand new, much more powerful PHP-based
  <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" target="_blank">MVC</a>
  framework I call VosaPHP. Using the new framework, I built over the course of several months the
  massive custom shopping cart system referred to as NeatoCart, which powers Neatorama.com's storefront,
  <a href="http://www.neatoshop.com" target="_blank">NeatoShop.com</a>. More than just a simple
  shopping cart, NeatoCart was also developed to support affiliate shops skinned and promoted by
  third-party websites. (Affiliate shops include <a href="http://shop.fark.com" target="_blank">Fark</a>
  and <a href="http://shop.boingboing.net" target="_blank">Boing Boing</a>.) In addition, I am Neatorama's
  system administrator, managing the 8 servers on which its collection of sites run. Neatorama receives
  over 3 million unique visitors per month.
</p>
<p>
  <b>2010</b> I used VosaPHP to build a software system for neatohub.com, another Neatorama
  property, which is a link-exchanging hub similar to <a href="http://2leep.com" target="_blank">2leep.com</a>.
  It functioned by allowing select third-party bloggers to embed a widget on their websites which would
  rotate links from other third-party neatohub blogs. It promised and delivered a 2:1 ratio, giving
  participants 200% of the traffic they sent into neatohub.
</p>
<p>
  <b>2011</b> I was contracted to build from scratch a very large scale blogging platform to
  replace WordPress for my client's high traffic blog. This is a work still in progress that is likely
  to take at least six months to complete.
</p>
<p>
  <b>2012</b> After about 8 months of development with VosaPHP, the new
  <a href="http://homgroup.com" target="_blank">HOMGroup.com</a> website was launched. It's the public-facing
  company website for H&Ocirc;M | Sotheby's International Realty that supports instant MLS property searching
  among many other features. Still in development are agent websites that will all be driven by the same back-end
  system to provide to H&Ocirc;M Group agents fully-customizable real estate websites.
</p>
<p>
  <b>2012</b> After about 8 months of development with VosaPHP, the new
  <a href="http://homgroup.com" target="_blank">HOMGroup.com</a> website was launched. It's the public-facing
  company website for H&Ocirc;M | Sotheby's International Realty that supports instant MLS property searching
  among many other features. Still in development are agent websites that will all be driven by the same back-end
  system to provide to H&Ocirc;M Group agents fully-customizable real estate websites.
</p>
<p style="padding-top:10px;font-size:75%;color:#bbb;text-align:right;">
  If you're wondering, yes, this page is this plain on purpose. <small>I like simple. Plus, the shoemaker's children and all that.</small> : )
</p>
</div>

<hr/>

<div class="body" style="font-size:0.9em;color:#555;">
<h2>Other Stuff</h2>
<p>
  <a href="/viet" title="Vietnamese Character Code Translator"><b>Convert Vietnamese Character Codes</b></a>
  -
  Use this tool to type normal characters (found on a US keyboard) into Vietnamese characters and also
  into the corresponding HTML character codes. This is useful whether you are just typing some text and you'd
  like to paste the raw Vietnamese characters into something like an email or if you need to paste the HTML
  entities into something like a web page.
</p>
</div>

<hr/>

<div class="body" style="font-size:0.85em;color:#555;">
<h2>From the Archives</h2>
<p>
I came across this old program I wrote a few years ago (in 2005). It's a desktop application that
I was toying with as a very simplified version of an MP3 playlist editor and MP3 player.
My goal was to make it simple and unobtrusive (see the image below) and in its current unfinished form, I
think I achieved that. The player is tiny and can be hidden/controlled (play, pause, previous, next) in the system
tray. Download, unzip, and give it a try if you're up to it: <a href="/LMEdit.zip">LMEdit.zip</a>.
<div align="center">
  <img src="/lmedit.jpg" alt="Minimal MP3 Player"/><br/>
  <small>A simple click on that tray icon will pause/unpause. This is essential if you're at work and need to pause without delay.</small>
</div>
<br/>
</p>
<hr/>
<p>
Here's another neat old app I wrote back in 2003. It's a binary clock and aside from telling time, its
main purpose is to illustrate how geeky cool you are to anyone who sees it on your computer screen.
Download it: <a href="/binclock.zip">binclock.zip</a>. Double-click to change the color of the virtual LEDs
and hit ESC to close it.
<div align="center">
  <img src="/binclock.gif" alt="Binary Clock Program"/> &nbsp; <img src="/binclock-yellow.gif" alt=""/><br/>
  <small>How quickly can you tell what times are shown here?</small>
</div>
<br/>
</p>
<?php /*
<hr>
<p>
For a little added fun, here are my latest video submissions at VideoSift:
</p>
<?php
  function dump_rss_items($i_feedurl, $i_maxlinks = 5) {
    $titles = array();
    $links = array();
    $descs = array();
    
    $url = preg_replace('@^.+//@', '', $i_feedurl);
    $url_parts = split('/', $url, 2);
    $server_parts = split(':', $url_parts[0], 2);
    $port = (count($server_parts) == 2) && is_numeric($server_parts[1]) ? $server_parts[1] : 80;

    // using fsockopen() instead of fopen() to use a connection timeout
    $handle = @fsockopen($server_parts[0], $port, $errno, $errstr, 1.0);

    if (!$handle)
      return;

    $uri = count($url_parts) == 2 ? "/{$url_parts[1]}" : '/';
    $out = "GET {$uri} HTTP/1.1\r\n";
    $out .= "Host: {$server_parts[0]}\r\n";
    $out .= "Connection: Close\r\n\r\n";
    @fwrite($handle, $out);

    $line = '';
    while (($next = fgets($handle, 4096)) !== FALSE) {
      // server has redirected us - load the new location
      if (preg_match('!Location: http://(.+)$!im', $next, $matches)) {
        @fclose($handle);

        $titles = array();
        $links = array();
        $descs = array();

        $line = '';

        $url_parts = split('/', $matches[1], 2);

        $handle = @fsockopen($server_parts[0], $port, $errno, $errstr, 1.0);

        if (!$handle)
          return FALSE;

        $uri = count($url_parts) == 2 ? "/{$url_parts[1]}" : '/';
        $out = "GET {$uri} HTTP/1.1\r\n";
        $out .= "Host: {$server_parts[0]}\r\n";
        $out .= "Connection: Close\r\n\r\n";
        @fwrite($handle, $out);

        continue;
      }

      $line .= $next;

      if (stripos($line, '<image>') !== FALSE) {
        if (stripos($line, '</image>') === FALSE)
          continue;

        $line = preg_replace('@<image>.*</image>@isU', '', $line);
      }

      if (stripos($line, '<title>') !== FALSE) {
        if (preg_match('@<title>(.*)</title>@isU', $line, $matches)) {
          $titles[] = preg_replace('@(^<!\\[CDATA\\[|\\]\\]>$)@', '', $matches[1]);

          $line = str_ireplace('<title>' . $matches[1] . '</title>', '', $line);
        }
        else
          continue;
      }

      if (stripos($line, '<link>') !== FALSE) {
        if (preg_match('@<link>(.*)</link>@isU', $line, $matches)) {
          $links[] = $matches[1];

          $line = str_ireplace('<link>' . $matches[1] . '</link>', '', $line);
        }
        else
          continue;
      }
      
      if (stripos($line, '<description>') !== FALSE) {
        if (preg_match('@<description>(.*)</description>@isU', $line, $matches)) {
          $descs[] = html_entity_decode(preg_replace('@(^<!\\[CDATA\\[|\\]\\]>$)@', '', $matches[1]));

          if (count($links) > $i_maxlinks)
            break;
          
          $line = str_ireplace('<description>' . $matches[1] . '</description>', '', $line);
        }
        else
          continue;
      }
    }

    fclose($handle);

    if (empty($links))
      return;
    
    // the first record is the site's name and url itself; skip it
    array_shift($titles);
    array_shift($links);
    array_shift($descs);

    $data = array();
    for ($i = 0; $i < count($links); ++$i) {
      $link = $links[$i];
      $data[] = array('link' => $link, 'title' => $titles[$i], 'desc' => $descs[$i]);
    }
    
    echo '<table border="0" width="100%">';
    
    foreach ($data as $idx => $vidinfo) {
      if (($idx % 2) == 0) {
        if ($idx > 0)
          echo '</tr>';
        echo '<tr>';
      }
      
      echo '<td>';
      
      $desc = '</a>' . preg_replace('@(views?\)).+@s', '\\1', $vidinfo['desc']);
      echo '<p class="video"><a href="' . $vidinfo['link'] . '" target="_blank">' .
        $vidinfo['title'] . ' <img src="http://static1.videosift.com/videosift/i/fullpage.gif" alt=""/><br />' .
        $desc . '</p><br />';
      
      echo '</td>';
    }
    
    echo '</tr>';
    echo '</table>';
  }

  dump_rss_items('http://www.videosift.com/rss2/lucky760/member.xml', 10);
?>
*/ ?>
</div>
</div>

<?php /*if (@$_GET['debug'])*/ { ?>
  <?php
  require_once(dirname(__FILE__) . '/db-test.inc');
  ?>

<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>

<script>
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
//
// from: http://davidwalsh.name/javascript-debounce-function
function debounce(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
};

<?php if (!@$_GET['debug']) { ?>

$('body').click(function(e){
  $.post(
    '/',
    {
      type : 'click',
      url : <?=json_encode($_SERVER['REQUEST_URI'])?>,
      x : e.pageX,
      y : e.pageY
    },
    function(data) {
//console.log('click:');
//console.log(data);
    },
    'json'
  );
});

$('body').mousemove(debounce(function(e){
  $.post(
    '/',
    {
      type : 'move',
      url : <?=json_encode($_SERVER['REQUEST_URI'])?>,
      x : e.pageX,
      y : e.pageY
    },
    function(data) {
//console.log('move:');
//console.log(data);
    },
    'json'
  );
}, 10));

<?php } else { ?>

var bw = $('body').width();
var bh = $('body').height();

var $canvas = $('<canvas width="' + bw + '" height="' + bh + '"></canvas>').css({ position : 'absolute', top : 0, left : 0 }).appendTo('body');
var canvas = $canvas.get(0);
var cw = canvas.width;
var ch = canvas.height;

var ctx = canvas.getContext('2d');

var imgdata = ctx.createImageData(2, 2);
var clickimgdata = ctx.createImageData(4, 4);

<?php

$max = 0;

if ($sth = DB::query("SELECT MAX(`count`) FROM breadcrumbs"))
  $max = $sth->fetchColumn();

$rows = DB::get_rows('breadcrumbs', ['id', 'type', 'x', 'y', 'count'], ['order' => 'id']);

foreach ($rows as list($id, $type, $x, $y, $count)) { ?>
  <?php
  $percent = round($count / $max * 100);
  
  if ($type == 'click') {
    $alpha = 160;
    $percent = min(100, $percent * 10);
    $pre = 'click';
  }
  else {
    $alpha = 80;
    $pre = '';
  }

  if ($percent >= 90)
    $rgb = [255, 0, 0];
  else if ($percent >= 80)
    $rgb = [255, 128, 0];
  else if ($percent >= 70)
    $rgb = [255, 255, 0];
  else if ($percent >= 60)
    $rgb = [128, 255, 0];
  else if ($percent >= 50)
    $rgb = [0, 255, 0];
  else if ($percent >= 40)
    $rgb = [0, 255, 128];
  else if ($percent >= 30)
    $rgb = [0, 255, 255];
  else if ($percent >= 20)
    $rgb = [0, 128, 255];
  else if ($percent >= 10)
    $rgb = [0, 0, 255];
  else
    $rgb = [0, 0, 128];
  ?>

  for (var i = 0; i < <?=$pre?>imgdata.data.length; i += 4) {
    <?=$pre?>imgdata.data[0 + i] = <?=$rgb[0]?>;
    <?=$pre?>imgdata.data[1 + i] = <?=$rgb[1]?>;
    <?=$pre?>imgdata.data[2 + i] = <?=$rgb[2]?>;
    <?=$pre?>imgdata.data[3 + i] = <?=$alpha?>;
  }

  ctx.putImageData(<?=$pre?>imgdata, <?=$x?>, <?=$y?>);
<?php
}
?>

var lastKnown = <?=intval($id)?>;

function plotNew() {
  $.post(
    '/',
    {
      action : 'refresh',
      lastid : lastKnown
    },
    function(data) {
      if (data.error)
        return;

      if (!data.plots || !data.plots.length)
        return;

      lastKnown = data.lastid;

      for (var i = 0; i < data.plots.length; ++i) {
        var plot = data.plots[i];

        var d = plot.type == 'click' ? clickimgdata : imgdata;

        for (var j = 0; j < d.data.length; j += 4) {
          d.data[0 + j] = plot.r;
          d.data[1 + j] = plot.g;
          d.data[2 + j] = plot.b;
          d.data[3 + j] = plot.a;
        }

        ctx.putImageData(d, plot.x, plot.y);
      }
    },
    'json'
  );
}

setInterval(plotNew, 1500);

<?php } ?>

</script>
<?php } ?>

</body>
</html>

<?php
if (!@$_GET['debug']) {
?>
  <script type="text/javascript">
  var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
  document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
  </script>
  <script type="text/javascript">
  var pageTracker = _gat._getTracker("UA-5016477-1");
  pageTracker._initData();
  pageTracker._trackPageview();
  </script>
<?php
}

