function jsFlickrBadge(json)
{
  var fn = function()
  {
    var dest = document.getElementById('jsFlickrBadge');
    if (dest)
    {
      var widgetTitle = document.getElementById('jsFlickrBadgeTitle');
      widgetTitle.href = json.link;
      while(dest.firstChild)
        dest.removeChild(dest.firstChild);
      var thumbWrapper = document.createElement('div');
      thumbWrapper.style.position = 'absolute';
      dest.appendChild(thumbWrapper);
      var num = jsFlickrBadgeConfig.rows * jsFlickrBadgeConfig.columns;
      var blank;
      if(jsFlickrBadgeConfig.animation == 'shuffle')
      {
        num--;
        blank = { row: jsFlickrBadgeConfig.rows - 1, col: jsFlickrBadgeConfig.columns - 1 };
      }
      var size = jsFlickrBadgeConfig.size;
      function makeThumb(photo, row, col)
      {
        if(photo.a) {
          photo.a.setAttribute('style', 'position:absolute;display:block;top:'+(row*size)+'px;left:'+(col*size)+'px;');
        }
        else {
          photo.a = document.createElement('a');
          photo.a.setAttribute('href', photo.link);
          photo.a.setAttribute('target', '_blank');
          photo.a.setAttribute('title', photo.title);
          photo.a.setAttribute('style', 'position:absolute;top:'+(row*size)+'px;left:'+(col*size)+'px;width:'+size+'px;height:'+size+'px;');
          photo.a.style.position = 'absolute';
          photo.a.style.top = (row*size) + 'px';
          photo.a.style.left = (col*size) + 'px';
          photo.a.style.width = size + 'px';
          photo.a.style.height = size + 'px';
          photo.a.style.border = 'none';
          photo.a.style.padding = '0';
          photo.a.style.margin = '0';
          photo.a.img = document.createElement('img');
          photo.a.img.setAttribute('alt', photo.title);
          photo.a.img.height=size;
          photo.a.img.width=size;
          photo.a.img.setAttribute('src', photo.media.m.replace(/_m\.jpg/, '_s.jpg'));
          photo.a.img.style.width = size + 'px';
          photo.a.img.style.height = size + 'px';
          photo.a.img.style.border = 'none';
          photo.a.img.style.padding = '0';
          photo.a.img.style.margin = '0';
          photo.a.appendChild(photo.a.img);
          thumbWrapper.appendChild(photo.a);
        }
        return photo.a;
      }
      var grid = [];
      var all = [];
      for (var i=0; i < num && i < json.items.length; i++)
      {
        var photo = json.items[i];
        var row = Math.floor(i / jsFlickrBadgeConfig.columns);
        var col = i % jsFlickrBadgeConfig.columns;
        var a = makeThumb(photo, row, col);
        if(col == 0)
          grid[row] = [a];
        else
          grid[row][col] = a;
	      a.jsFlickrBadge = {row: row, col: col};
        all.push(a);
      }
      if(jsFlickrBadgeConfig.animation == 'shuffle')
      {
        function up() { return { row: blank.row - 1, col: blank.col, last: 'up' }; }
        function down() { return { row: blank.row + 1, col: blank.col, last: 'down' }; }
        function left() { return { row: blank.row, col: blank.col - 1, last: 'left'}; }
        function right() { return { row: blank.row, col: blank.col + 1, last: 'right'}; }
        function shuffle()
        {
          var moves = [];
          if(blank.row > 0 && blank.last != 'down')
            moves.push(up);
          if(blank.row + 1 < grid.length && blank.last != 'up')
            moves.push(down);
          if(blank.col > 0 && blank.last != 'right')
            moves.push(left);
          if(blank.col + 1 < grid[0].length && blank.last != 'left')
            moves.push(right);
          var from = moves[Math.floor(Math.random() * moves.length)]();
          var x, y;
          if(blank.col > from.col) {
            x = size;
            y = 0;
          }
          else if(blank.col < from.col) {
            x = -size;
            y = 0;
          }
          else if(blank.row > from.row) {
            x = 0;
            y = size;
          }
          else if(blank.row < from.row) {
            x = 0;
            y = -size;
          }
          new Effect.Move(grid[from.row][from.col], { x: x, y: y, mode: 'relative',
            afterFinish: function() {
              grid[blank.row][blank.col] = grid[from.row][from.col];
              delete grid[from.row][from.col];
              blank = from;
              window.setTimeout(shuffle, 1000);
            }
          });
        }
        window.setTimeout(shuffle, 1000);
      }
      else if(jsFlickrBadgeConfig.animation == 'zoom' && all.length > 1)
      {
	      var lastZoomed = 0;
	      function ne(o) { return { row: o.row - 1, col: o.col, x: 0, y: 1 }; }
	      function nw(o) { return { row: o.row - 1, col: o.col - 1, x: 1, y: 1 }; }
	      function se(o) { return { row: o.row, col: o.col, x: 0, y: 0 }; }
	      function sw(o) { return { row: o.row, col: o.col - 1, x: 1, y: 0 }; }
	      var zoomA = document.createElement('a');
	      zoomA.setAttribute('target', '_blank');
	      Element.setStyle(zoomA, {
		      position: 'absolute',
		      display: 'none'
				});
	      zoomA.img = document.createElement('img');
	      zoomA.appendChild(zoomA.img);
	      thumbWrapper.appendChild(zoomA);
        function zoom()
        {
	        var i = lastZoomed;
	        while(i == lastZoomed)
		        i = Math.floor(Math.random() * all.length);
	        var a = all[i];
	        lastZoomed = i;
	        var info = a.jsFlickrBadge;
	        var dirs = [];
	        if(info.row > 0 && info.col + 1 < grid[0].length)
		        dirs.push(ne);
	        if(info.row > 0 && info.col > 0)
		        dirs.push(nw);
	        if(info.row + 1 < grid.length && info.col + 1 < grid[0].length)
		        dirs.push(se);
	        if(info.row + 1 < grid.length && info.col > 0)
	          dirs.push(sw);
					dir = dirs[Math.floor(Math.random() * dirs.length)](info);

	        zoomA.setAttribute('href', a.href);
	        zoomA.setAttribute('title', a.title);
	        zoomA.img.setAttribute('alt', a.img.alt);
	        zoomA.img.setAttribute('src', a.img.src);
	        Element.setStyle(zoomA.img, {
		        height: (2*size) + 'px',
		        width: (2*size) + 'px'
					});
	        Element.setStyle(zoomA, {
					  position: 'absolute',
			      height: (2*size) + 'px',
					  width: (2*size) + 'px',
			      top: (dir.row*size) + 'px',
			      left: (dir.col*size) + 'px',
			      display: 'none',
					  zIndex: 1000
					});
	        new Effect.Appear(zoomA, {
				    duration: 2,
						afterFinish: function() {
							window.setTimeout(function() {
								new Effect.Parallel([
									new Effect.Scale(zoomA, 50, {
												sync: true,
												duration: 0.5,
												afterUpdate: function() {
													zoomA.img.style.width = zoomA.style.width;
													zoomA.img.style.height = zoomA.style.height;
												}
											}),
									new Effect.Move(zoomA, {
										sync: true,
										duration: 0.5,
										x: dir.x * size,
										y: dir.y * size
									})
								], {
									afterFinish: function() {
										Element.hide(zoomA);
										window.setTimeout(zoom, 1000);
									}
								});
							}, 1000);
						}
					});
				}
	      window.setTimeout(zoom, 1000);
      }
      else if(jsFlickrBadgeConfig.animation == 'vscroll' && grid.length > 1)
      {
        var i = jsFlickrBadgeConfig.rows * jsFlickrBadgeConfig.columns % json.items.length;
        function vscroll() {
          var newRow = [];
          for(; newRow.length < jsFlickrBadgeConfig.columns; i = (i + 1) % json.items.length)
            newRow.push(makeThumb(json.items[i], jsFlickrBadgeConfig.rows, newRow.length));
          new Effect.Move(thumbWrapper, {
            y: -size,
            mode: 'relative',
            duration: 2,
            afterFinish: function() {
              for(var k=0;k<jsFlickrBadgeConfig.columns;k++)
                grid[0][k].style.top = -size + 'px';
              for(var j=0;j<jsFlickrBadgeConfig.rows-1;j++)
                grid[j] = grid[j+1];
              grid[jsFlickrBadgeConfig.rows-1] = newRow;
              for(var j=0;j<jsFlickrBadgeConfig.rows;j++)
                for(var k=0;k<jsFlickrBadgeConfig.columns;k++) {
                  grid[j][k].style.top = (j*size) + 'px';
                }
              thumbWrapper.style.top = '0';
              window.setTimeout(vscroll, 5000);
            }
          });
        }
        window.setTimeout(vscroll, 5000);
      }
    }
  else
      window.setTimeout(fn, 50);
  };
  fn();
}

