// 
// Parallax 0.1
// 
// Add a simple parallax effect to a page
// 
// Requires jQuery. Tested with v1.3.2.
// 
// options: object, Contains all the options required to run the parallax effect:
// options.container: string, The selector of the container element (optional)
// options.useHTML: boolean, If set to true, options.container is optional as the
//   system will use the HTML element instead of the container to capture mousemove
//   events
// options.elements: array, An array of objects of the following structure:
//   {
//     'selector': 'div.test',
//     'properties': {
//       'x': {
//         'left': {
//           'initial': 0,
//           'multiplier': 0.1,
//           'min': -160,
//           'max': 160
//         }
//       },
//       'y': {
//          'top': {
//           'initial': 0,
//           'multiplier': 0.1,
//           'min': 90,
//           'max': 110
//          }
//       }
//     }
//   }
// 
// options.elements[n].selector: string, The jQuery selector for the element
// options.elements[n].properties: object, Contains 'x' and 'y' keys for the properties
//   that are affected by either horizontal, or vertical movement respectively
// options.elements[n].properties[x || y]: object, Contains keys relating to the CSS
//   property to be changed on movement
// options.elements[n].properties[x || y][cssProperty]: object, Contains two keys
//   'initial' and 'multiplier'. Initial is the starting point for the property and
//   multiplier is used to create the parallax effect. For example to have the element
//   move exactly with the mouse cursor you'd use 1, lower values move less...
//   'min' and 'max' should be fairly self explanetory, the value will be prevented from
//   deviating beyond these boundaries (both are optional)
// 
// Free to use anywhere for anything, but I'd love to see what anyone does with it...
// 
// dom111.co.uk
// 
function Parallax(options) {
  // check jQuery is loaded...
  if (!jQuery) {
    throw new Error('Missing jQuery!');
  }
  
  // options
  var options = jQuery.extend({
    // container: the main element
    'container': 'div.parallax',
    // useHTML: use the whole document as a listener
    'useHTML': true,
    // elements: the elements to manipulate
    'elements': []
  }, options || {});
  
  // attach the mousemove event to the specified element
  jQuery((options.useHTML) ? 'html' : options.container).mousemove(function(e) {
    // set up the element as a variable
    var el = jQuery(this);
    
    // calculate the center
    var center = {
      'x': Math.floor(parseInt(el.width()) / 2),
      'y': Math.floor(parseInt(el.height()) / 2)
    }
    
    // the the cursor's position
    var pos = {
      'x': (e.pageX - el.offset().left),
      'y': (e.pageY - el.offset().top)
    }
    
    // calculate the offset
    var offset = {
      'x': (pos.x - center.x),
      'y': (pos.y - center.y)
    }
    
    // loop through all the elements
    for (var i = options.elements.length - 1; i >= 0; i--) {
      // set up a container for the properties
      var opts = {}, value, p;

      // loop through all the properties specified
      for (var property in options.elements[i].properties.x) {
        // store the objet in a nicer variable
        p = options.elements[i].properties.x[property];
        // set the value
        value = p.initial + (offset.x * p.multiplier);
        
        // check that the value's within the bounds
        if (p.min && value < p.min) {
          value = p.min;

        } else if (p.max && value > p.max) {
          value = p.max;
        }
        
        // append it
        opts[property] = value;
      }

      for (var property in options.elements[i].properties.y) {
        p = options.elements[i].properties.y[property];
        value = p.initial + (offset.y * p.multiplier);

        if (p.min && value < p.min) {
          value = p.min;

        } else if (p.max && value > p.max) {
          value = p.max;
        }

        opts[property] = value;
      }
      
      // fix for firefox
      if ('background-position-x' in opts || 'background-position-y' in opts) {
        opts['background-position'] = '' + ((opts['background-position-x']) ? opts['background-position-x'] : '0') + 'px ' + ((opts['background-position-y']) ? opts['background-position-y'] : '0') + 'px';
        
        delete opts['background-position-x'];
        delete opts['background-position-y'];
      }
      
      // here's the magic! simples!
      jQuery(options.elements[i].selector).css(opts);
    };
  });
}
