Solved

What's wrong with this code?

Posted on 2013-01-28
5
316 Views
Last Modified: 2013-01-30
I have a Javascript puzzle that works fine in Safari, Chrome and IE9, but does not work in FireFox, Opera, or IE7 or 8. Anyone script guru able to see what the issue is?

Here's the link to the puzzle: http://imagebank.totopartners.com/puzzles/puzzle-pfi/people-first-innovation.html

Here's my script and html



var _image_path = "img4.jpg";

var _image_width =  426;
var _image_height = 640;

var _max_rows = 3;
var _max_cols = 3;

var _num_rows = 3;
var _num_cols = 3;

// figure out how wide and tall each tile should be
var _tile_width = _image_width / _num_cols;
var _tile_height = _image_height / _num_rows;

var _empty_tile = 6; // id of position of empty tile

// note: rows, columns, and positions all start with 0


/*
 * Summary: Adds puzzle tiles to wrapper div.
 */
function createTiles(){

  // add tiles by iterating over all row/column combinations
  for (r=0; r<_num_rows; r++) {
    for (c=0; c<_num_cols; c++) {
      var tile = new createDiv (_tile_width, _tile_height, r, c);
     
      // set the empty tile
      if (tile.div.position_id == _empty_tile){
        tile.div.style.opacity = 0.0;
      }
      document.getElementById("wrapper").appendChild(tile.div);
    }
  }
}


/*
 * Summary: Returns a div with the specified width and height and puts it at the desired position (based on the supplied row / column)
 * Parameters: Div width in px, height in px, row index, and column index
 * Returns: The div you created
 */
function createDiv(width, height, row, column){
  this.div = document.createElement('div');

  // position_id is an index going from left to right across all the rows of the puzzle
  this.div.position_id = row*(_num_cols) + column;

  this.div.style.width = width + "px";
  this.div.style.height = height + "px";

  this.div.style.position = "relative";
  this.div.style.float = "left";

  // sets the div's background
  this.div.style['background-image'] = "url("+_image_path+")";
  this.div.style['background-position'] = "-" + column*width + "px -" + row*height + "px";
  this.div.style.opacity = 1.0;

  // tile border aesthetics
  this.div.style['border-style'] = "solid";
  this.div.style['border-width'] = "2px";
  this.div.style['border-color'] = "#1F1F1F";
  this.div.style.margin = "-1px";

  // event handler to move the clicked div to the empty tile location if the div is in a valid position
  this.div.onclick = tileClicked;
 
      // return div
  return this;
}


/*
 * Summary: initializes parameters for moveTiles function when a tile is clicked
 * Parameters: event (occurs onclick)
 */
function tileClicked(event){
 
  var active_tile = event.srcElement;   // the div of the tile that was clicked
  var empty_tile = active_tile.parentNode.childNodes[_empty_tile];   // the div of the empty tile (the "destination")

  moveTiles(active_tile, empty_tile);   // move active tile to destination tile if they are adjacent
}

/*
 * Summary: moves active tile to destination tile if they are adjacent
 * Parameters: active tile (the tile that was clicked on) and the empty tile
 */
function moveTiles(active_tile, empty_tile) {
  // check if active tile is adjacent to empty tile
    if (active_tile.position_id + 1 == _empty_tile
    || active_tile.position_id - 1 == _empty_tile
    || active_tile.position_id + _num_cols == _empty_tile
    || active_tile.position_id - _num_cols == _empty_tile) {

      // if active tile is adjacent, transfer background to empty tile and grey-out background of active tile
      empty_tile.style['background-position'] = active_tile.style['background-position'];
      empty_tile.style.opacity = 1.0;
      active_tile.style.opacity = 0.0;

      // set empty tile id to id of previous active tile
      _empty_tile = active_tile.position_id;
    }
    else {
      return;
    }
  }


/*
 * Summary: shuffle up the tiles in the beginning of the game by making many valid, random moves
 */
function shuffleTiles(){

  // make a certain large number number of moves (currently = number of rows * number of columns * 5)
  for (k=0; k<(_num_rows * _num_cols * 5); k++) {

    // for every move, make one of 4 moves (if valid)
    var rand = Math.floor(Math.random()*4)

    switch (rand) {
      case 0:
        if(_empty_tile - 1 < 0) {   // if left tile does not exist, go to next move
          // shuffleTiles();   // can shuffle tiles instead of breaking to next iteration if more complexity are desired
          break;
        }
        else {
          var active_tile = document.getElementById("wrapper").childNodes[_empty_tile - 1];   // find left tile
          var empty_tile = document.getElementById("wrapper").childNodes[_empty_tile];   // find empty tile
          moveTiles(active_tile, empty_tile);   // switch tiles
          break;
        }
      case 1:
        if(_empty_tile + 1 >= _num_cols) {   // if right tile does not exist, go to next move
          // shuffleTiles();
          break;
        }
        else {
          var active_tile = document.getElementById("wrapper").childNodes[_empty_tile + 1];   // find right tile
          var empty_tile = document.getElementById("wrapper").childNodes[_empty_tile];   // find empty tile
          moveTiles(active_tile, empty_tile);   // switch tiles
          break;
        }
      case 2:
        if(_empty_tile - _num_cols < 0) {   // if tile above does not exist, go to next move
          // shuffleTiles();
          break;
        }
        else {
          var active_tile = document.getElementById("wrapper").childNodes[_empty_tile - _num_cols];   // find tile above
          var empty_tile = document.getElementById("wrapper").childNodes[_empty_tile];   // find empty tile
          moveTiles(active_tile, empty_tile);   // switch tiles
          break;
        }
      case 3:
        if(_empty_tile + _num_cols > (_num_cols * _num_rows - 1) ) {   // if tile below does not exist, go to next move
          // shuffleTiles();
          break;
        }
        else {
          var active_tile = document.getElementById("wrapper").childNodes[_empty_tile + _num_cols];   // find tile below
          var empty_tile = document.getElementById("wrapper").childNodes[_empty_tile];   // find empty tile
          moveTiles(active_tile, empty_tile);   // switch tiles
          break;
        }
    }
  }
}


/*
 * Summary: Generates a new random puzzle
 */
function generateRandomPuzzle(){
  // removes previous puzzle tiles
  document.getElementById("wrapper").innerHTML = "";

  // randomize image and number of tiles
  _image_path = "img4.jpg";
  _num_rows = 3;
  _num_cols = 3;

  _tile_width = _image_width / _num_cols;
  _tile_height = _image_height / _num_rows;

  _empty_tile = 6; // id of position of empty tile

  createTiles();   // create new puzzle

  // this function does not shuffle puzzle, so user can see what final image is supposed to look like prior to shuffling
  // shuffleTiles();
}


/*
 * When the page loads, create the puzzle
 */
window.onload = function () {
  // generate parameters for a random puzzle
  // create the tiles

  // set wrapper to hold tiles
  document.getElementById("wrapper").style.width = _image_width + 20 + "px";
  document.getElementById("wrapper").height = _image_height + 20 + "px";

  // center wrapper
  document.getElementById("wrapper").style['margin-left'] = "auto";
  document.getElementById("wrapper").style['margin-right'] = "auto";
  document.getElementById("wrapper").style.display = "table";

  // create footer for controls
  document.getElementById("footer").style['margin-left'] = "auto";
  document.getElementById("footer").style['margin-right'] = "auto";

  createTiles();
      shuffleTiles();

}


HTML


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Sliding Puzzle - People-First Innovation</title>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  

        <link href="http://fonts.googleapis.com/css?family=Oswald:300" rel="stylesheet" type="text/css" />
    </head>
    <body style="background-color:#1F1F1F;">
          <div style="text-align:center;">
                <p style="font-family: 'Oswald', sans-serif; font-size:28pt; line-height:40%; color:#FFFFFF;">tile puzzle challenge</p>
                <p style="font-family: 'Oswald', sans-serif; font-size:14pt; line-height:60%; color:#FFFFFF;">[the solution's open tile will always be the lower left tile]</p><br /><br />
          </div>
          <div id="wrapper" style="display:block;"></div><br />
          <div id="footer" style="text-align:center;">
                      <p style="font-family: 'Oswald', sans-serif; font-size:12pt; line-height:60%; color:#FFFFFF;">
                            [click on a tile to move it to the open space]
                      </p>
          </div>
         <script  type="text/javascript" src="p2.js"></script>         
    </body>
</html>
0
Comment
Question by:GAGriff
5 Comments
 
LVL 18

Expert Comment

by:nap0leon
ID: 38828195
In FireFox 10 and IE8 I noticed that the background-image styles are missing.
Looks like your "image path" needs another set of quotes in the line where you are setting it:

this.div.style['background-image'] = "url("+_image_path+")";

Open in new window

to
this.div.style['background-image'] = "url('"+_image_path+"')";

Open in new window


the resulting HTML should look like
url('img4.jpg')

Open in new window

and not
url(img4.jpg)

Open in new window

0
 

Author Comment

by:GAGriff
ID: 38829480
Thanks for the tip, that did help load a image, but still doesn't function. I did fool around with the Float style and got it to build the puzzle array, but with not the right background positions.  Seems like Firefox drops everything after the image, not getting any of the other styling.

GAGriff
0
 
LVL 9

Expert Comment

by:Sar1973
ID: 38830427
Have you checked the page/code errors with a validator?
Also, watch out how you manage the moveTiles function test: the "+" sign is often misunderstood for a character concatenate operation by the compilers.
Finally, I'd remember you that events are not managed in the same way in all browsers; some of them nedd event handlers.
0
 
LVL 35

Accepted Solution

by:
Robert Schutt earned 500 total points
ID: 38831499
I concentrated on FireFox (up-to-date):

* instead of using style[...] I changed them all to
this.div.style.backgroundImage = ...

Open in new window

(note the capital letter if the original had a dash)
so these as well:
.style.marginLeft = ...

Open in new window


* after that I noticed the float didn't work (all pieces below each other in one long line), if that's an issue for you then instead of setting style.float on the divs, use
this.div.className = 'floatleft';

Open in new window

and define the class in the <head> of the HTML
<style type="text/css">
	div.floatleft {
		float: left;
	}
</style>

Open in new window


* in the tileClicked function, I noticed in FireBug that event.srcElement was null so I changed the first line to:
var active_tile = event.srcElement || event.target;   // the div of the tile that was clicked

Open in new window


[older IE's may be real fussy about the doctype]
0
 

Author Closing Comment

by:GAGriff
ID: 38832274
Yes lots of variables to fix, but this gets me toward a solution.

Thanks,

GAGriff
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Suggested Solutions

This article shows how to create and access 2-dimensional arrays in JavaScript.  It includes a tutorial in case you are just trying to "get your head wrapped around" the concept and we'll also look at some useful tips for more advanced programmers. …
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now