// Copyright 2006 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


// Known Issues:
//
// * Patterns are not implemented.
// * Radial gradient are not implemented. The VML version of these look very
//   different from the canvas one.
// * Clipping paths are not implemented.
// * Coordsize. The width and height attribute have higher priority than the
//   width and height style values which isn't correct.
// * Painting mode isn't implemented.
// * Canvas width/height should is using content-box by default. IE in
//   Quirks mode will draw the canvas using border-box. Either change your
//   doctype to HTML5
//   (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
//   or use Box Sizing Behavior from WebFX
//   (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
// * Non uniform scaling does not correctly scale strokes.
// * Optimize. There is always room for speed improvements.

// Only add this code if we do not already have a canvas implementation
;
if (!document.createElement('canvas').getContext) {

(function() {

  // alias some functions to make (compiled) code shorter
  var m = Math;
  var mr = m.round;
  var ms = m.sin;
  var mc = m.cos;
  var abs = m.abs;
  var sqrt = m.sqrt;

  // this is used for sub pixel precision
  var Z = 10;
  var Z2 = Z / 2;

  /**
   * This funtion is assigned to the <canvas> elements as element.getContext().
   * @this {HTMLElement}
   * @return {CanvasRenderingContext2D_}
   */
  function getContext() {
    return this.context_ ||
        (this.context_ = new CanvasRenderingContext2D_(this));
  }

  var slice = Array.prototype.slice;

  /**
   * Binds a function to an object. The returned function will always use the
   * passed in {@code obj} as {@code this}.
   *
   * Example:
   *
   *   g = bind(f, obj, a, b)
   *   g(c, d) // will do f.call(obj, a, b, c, d)
   *
   * @param {Function} f The function to bind the object to
   * @param {Object} obj The object that should act as this when the function
   *     is called
   * @param {*} var_args Rest arguments that will be used as the initial
   *     arguments when the function is called
   * @return {Function} A new function that has bound this
   */
  function bind(f, obj, var_args) {
    var a = slice.call(arguments, 2);
    return function() {
      return f.apply(obj, a.concat(slice.call(arguments)));
    };
  }

  var G_vmlCanvasManager_ = {
    init: function(opt_doc) {
      if (/MSIE/.test(navigator.userAgent) && !window.opera) {
        var doc = opt_doc || document;
        // Create a dummy element so that IE will allow canvas elements to be
        // recognized.
        doc.createElement('canvas');
        doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));
      }
    },

    init_: function(doc) {
      // create xmlns
      if (!doc.namespaces['g_vml_']) {
        doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml',
                           '#default#VML');

      }
      if (!doc.namespaces['g_o_']) {
        doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office',
                           '#default#VML');
      }

      // Setup default CSS.  Only add one style sheet per document
      if (!doc.styleSheets['ex_canvas_']) {
        var ss = doc.createStyleSheet();
        ss.owningElement.id = 'ex_canvas_';
        ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +
            // default size is 300x150 in Gecko and Opera
            'text-align:left;width:300px;height:150px}' +
            'g_vml_\\:*{behavior:url(#default#VML)}' +
            'g_o_\\:*{behavior:url(#default#VML)}';

      }

      // find all canvas elements
      var els = doc.getElementsByTagName('canvas');
      for (var i = 0; i < els.length; i++) {
        this.initElement(els[i]);
      }
    },

    /**
     * Public initializes a canvas element so that it can be used as canvas
     * element from now on. This is called automatically before the page is
     * loaded but if you are creating elements using createElement you need to
     * make sure this is called on the element.
     * @param {HTMLElement} el The canvas element to initialize.
     * @return {HTMLElement} the element that was created.
     */
    initElement: function(el) {
      if (!el.getContext) {

        el.getContext = getContext;

        // Remove fallback content. There is no way to hide text nodes so we
        // just remove all childNodes. We could hide all elements and remove
        // text nodes but who really cares about the fallback content.
        el.innerHTML = '';

        // do not use inline function because that will leak memory
        el.attachEvent('onpropertychange', onPropertyChange);
        el.attachEvent('onresize', onResize);

        var attrs = el.attributes;
        if (attrs.width && attrs.width.specified) {
          // TODO: use runtimeStyle and coordsize
          // el.getContext().setWidth_(attrs.width.nodeValue);
          el.style.width = attrs.width.nodeValue + 'px';
        } else {
          el.width = el.clientWidth;
        }
        if (attrs.height && attrs.height.specified) {
          // TODO: use runtimeStyle and coordsize
          // el.getContext().setHeight_(attrs.height.nodeValue);
          el.style.height = attrs.height.nodeValue + 'px';
        } else {
          el.height = el.clientHeight;
        }
        //el.getContext().setCoordsize_()
      }
      return el;
    }
  };

  function onPropertyChange(e) {
    var el = e.srcElement;

    switch (e.propertyName) {
      case 'width':
        el.style.width = el.attributes.width.nodeValue + 'px';
        el.getContext().clearRect();
        break;
      case 'height':
        el.style.height = el.attributes.height.nodeValue + 'px';
        el.getContext().clearRect();
        break;
    }
  }

  function onResize(e) {
    var el = e.srcElement;
    if (el.firstChild) {
      el.firstChild.style.width =  el.clientWidth + 'px';
      el.firstChild.style.height = el.clientHeight + 'px';
    }
  }

  G_vmlCanvasManager_.init();

  // precompute "00" to "FF"
  var dec2hex = [];
  for (var i = 0; i < 16; i++) {
    for (var j = 0; j < 16; j++) {
      dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);
    }
  }

  function createMatrixIdentity() {
    return [
      [1, 0, 0],
      [0, 1, 0],
      [0, 0, 1]
    ];
  }

  function matrixMultiply(m1, m2) {
    var result = createMatrixIdentity();

    for (var x = 0; x < 3; x++) {
      for (var y = 0; y < 3; y++) {
        var sum = 0;

        for (var z = 0; z < 3; z++) {
          sum += m1[x][z] * m2[z][y];
        }

        result[x][y] = sum;
      }
    }
    return result;
  }

  function copyState(o1, o2) {
    o2.fillStyle     = o1.fillStyle;
    o2.lineCap       = o1.lineCap;
    o2.lineJoin      = o1.lineJoin;
    o2.lineWidth     = o1.lineWidth;
    o2.miterLimit    = o1.miterLimit;
    o2.shadowBlur    = o1.shadowBlur;
    o2.shadowColor   = o1.shadowColor;
    o2.shadowOffsetX = o1.shadowOffsetX;
    o2.shadowOffsetY = o1.shadowOffsetY;
    o2.strokeStyle   = o1.strokeStyle;
    o2.globalAlpha   = o1.globalAlpha;
    o2.arcScaleX_    = o1.arcScaleX_;
    o2.arcScaleY_    = o1.arcScaleY_;
    o2.lineScale_    = o1.lineScale_;
  }

  function processStyle(styleString) {
    var str, alpha = 1;

    styleString = String(styleString);
    if (styleString.substring(0, 3) == 'rgb') {
      var start = styleString.indexOf('(', 3);
      var end = styleString.indexOf(')', start + 1);
      var guts = styleString.substring(start + 1, end).split(',');

      str = '#';
      for (var i = 0; i < 3; i++) {
        str += dec2hex[Number(guts[i])];
      }

      if (guts.length == 4 && styleString.substr(3, 1) == 'a') {
        alpha = guts[3];
      }
    } else {
      str = styleString;
    }

    return {color: str, alpha: alpha};
  }

  function processLineCap(lineCap) {
    switch (lineCap) {
      case 'butt':
        return 'flat';
      case 'round':
        return 'round';
      case 'square':
      default:
        return 'square';
    }
  }

  /**
   * This class implements CanvasRenderingContext2D interface as described by
   * the WHATWG.
   * @param {HTMLElement} surfaceElement The element that the 2D context should
   * be associated with
   */
  function CanvasRenderingContext2D_(surfaceElement) {
    this.m_ = createMatrixIdentity();

    this.mStack_ = [];
    this.aStack_ = [];
    this.currentPath_ = [];

    // Canvas context properties
    this.strokeStyle = '#000';
    this.fillStyle = '#000';

    this.lineWidth = 1;
    this.lineJoin = 'miter';
    this.lineCap = 'butt';
    this.miterLimit = Z * 1;
    this.globalAlpha = 1;
    this.canvas = surfaceElement;

    var el = surfaceElement.ownerDocument.createElement('div');
    el.style.width =  surfaceElement.clientWidth + 'px';
    el.style.height = surfaceElement.clientHeight + 'px';
    el.style.overflow = 'hidden';
    el.style.position = 'absolute';
    surfaceElement.appendChild(el);

    this.element_ = el;
    this.arcScaleX_ = 1;
    this.arcScaleY_ = 1;
    this.lineScale_ = 1;
  }

  var contextPrototype = CanvasRenderingContext2D_.prototype;
  contextPrototype.clearRect = function() {
    this.element_.innerHTML = '';
  };

  contextPrototype.beginPath = function() {
    // TODO: Branch current matrix so that save/restore has no effect
    //       as per safari docs.
    this.currentPath_ = [];
  };

  contextPrototype.moveTo = function(aX, aY) {
    var p = this.getCoords_(aX, aY);
    this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y});
    this.currentX_ = p.x;
    this.currentY_ = p.y;
  };

  contextPrototype.lineTo = function(aX, aY) {
    var p = this.getCoords_(aX, aY);
    this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y});

    this.currentX_ = p.x;
    this.currentY_ = p.y;
  };

  contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
                                            aCP2x, aCP2y,
                                            aX, aY) {
    var p = this.getCoords_(aX, aY);
    var cp1 = this.getCoords_(aCP1x, aCP1y);
    var cp2 = this.getCoords_(aCP2x, aCP2y);
    bezierCurveTo(this, cp1, cp2, p);
  };

  // Helper function that takes the already fixed cordinates.
  function bezierCurveTo(self, cp1, cp2, p) {
    self.currentPath_.push({
      type: 'bezierCurveTo',
      cp1x: cp1.x,
      cp1y: cp1.y,
      cp2x: cp2.x,
      cp2y: cp2.y,
      x: p.x,
      y: p.y
    });
    self.currentX_ = p.x;
    self.currentY_ = p.y;
  }

  contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
    // the following is lifted almost directly from
    // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes

    var cp = this.getCoords_(aCPx, aCPy);
    var p = this.getCoords_(aX, aY);

    var cp1 = {
      x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_),
      y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_)
    };
    var cp2 = {
      x: cp1.x + (p.x - this.currentX_) / 3.0,
      y: cp1.y + (p.y - this.currentY_) / 3.0
    };

    bezierCurveTo(this, cp1, cp2, p);
  };

  contextPrototype.arc = function(aX, aY, aRadius,
                                  aStartAngle, aEndAngle, aClockwise) {
    aRadius *= Z;
    var arcType = aClockwise ? 'at' : 'wa';

    var xStart = aX + mc(aStartAngle) * aRadius - Z2;
    var yStart = aY + ms(aStartAngle) * aRadius - Z2;

    var xEnd = aX + mc(aEndAngle) * aRadius - Z2;
    var yEnd = aY + ms(aEndAngle) * aRadius - Z2;

    // IE won't render arches drawn counter clockwise if xStart == xEnd.
    if (xStart == xEnd && !aClockwise) {
      xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something
                       // that can be represented in binary
    }

    var p = this.getCoords_(aX, aY);
    var pStart = this.getCoords_(xStart, yStart);
    var pEnd = this.getCoords_(xEnd, yEnd);

    this.currentPath_.push({type: arcType,
                           x: p.x,
                           y: p.y,
                           radius: aRadius,
                           xStart: pStart.x,
                           yStart: pStart.y,
                           xEnd: pEnd.x,
                           yEnd: pEnd.y});

  };

  contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
  };

  contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
    var oldPath = this.currentPath_;
    this.beginPath();

    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
    this.stroke();

    this.currentPath_ = oldPath;
  };

  contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
    var oldPath = this.currentPath_;
    this.beginPath();

    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
    this.fill();

    this.currentPath_ = oldPath;
  };

  contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
    var gradient = new CanvasGradient_('gradient');
    gradient.x0_ = aX0;
    gradient.y0_ = aY0;
    gradient.x1_ = aX1;
    gradient.y1_ = aY1;
    return gradient;
  };

  contextPrototype.createRadialGradient = function(aX0, aY0, aR0,
                                                   aX1, aY1, aR1) {
    var gradient = new CanvasGradient_('gradientradial');
    gradient.x0_ = aX0;
    gradient.y0_ = aY0;
    gradient.r0_ = aR0;
    gradient.x1_ = aX1;
    gradient.y1_ = aY1;
    gradient.r1_ = aR1;
    return gradient;
  };

  contextPrototype.drawImage = function(image, var_args) {
    var dx, dy, dw, dh, sx, sy, sw, sh;

    // to find the original width we overide the width and height
    var oldRuntimeWidth = image.runtimeStyle.width;
    var oldRuntimeHeight = image.runtimeStyle.height;
    image.runtimeStyle.width = 'auto';
    image.runtimeStyle.height = 'auto';

    // get the original size
    var w = image.width;
    var h = image.height;

    // and remove overides
    image.runtimeStyle.width = oldRuntimeWidth;
    image.runtimeStyle.height = oldRuntimeHeight;

    if (arguments.length == 3) {
      dx = arguments[1];
      dy = arguments[2];
      sx = sy = 0;
      sw = dw = w;
      sh = dh = h;
    } else if (arguments.length == 5) {
      dx = arguments[1];
      dy = arguments[2];
      dw = arguments[3];
      dh = arguments[4];
      sx = sy = 0;
      sw = w;
      sh = h;
    } else if (arguments.length == 9) {
      sx = arguments[1];
      sy = arguments[2];
      sw = arguments[3];
      sh = arguments[4];
      dx = arguments[5];
      dy = arguments[6];
      dw = arguments[7];
      dh = arguments[8];
    } else {
      throw Error('Invalid number of arguments');
    }

    var d = this.getCoords_(dx, dy);

    var w2 = sw / 2;
    var h2 = sh / 2;

    var vmlStr = [];

    var W = 10;
    var H = 10;

    // For some reason that I've now forgotten, using divs didn't work
    vmlStr.push(' <g_vml_:group',
                ' coordsize="', Z * W, ',', Z * H, '"',
                ' coordorigin="0,0"' ,
                ' style="width:', W, 'px;height:', H, 'px;position:absolute;');

    // If filters are necessary (rotation exists), create them
    // filters are bog-slow, so only create them if abbsolutely necessary
    // The following check doesn't account for skews (which don't exist
    // in the canvas spec (yet) anyway.

    if (this.m_[0][0] != 1 || this.m_[0][1]) {
      var filter = [];

      // Note the 12/21 reversal
      filter.push('M11=', this.m_[0][0], ',',
                  'M12=', this.m_[1][0], ',',
                  'M21=', this.m_[0][1], ',',
                  'M22=', this.m_[1][1], ',',
                  'Dx=', mr(d.x / Z), ',',
                  'Dy=', mr(d.y / Z), '');

      // Bounding box calculation (need to minimize displayed area so that
      // filters don't waste time on unused pixels.
      var max = d;
      var c2 = this.getCoords_(dx + dw, dy);
      var c3 = this.getCoords_(dx, dy + dh);
      var c4 = this.getCoords_(dx + dw, dy + dh);

      max.x = m.max(max.x, c2.x, c3.x, c4.x);
      max.y = m.max(max.y, c2.y, c3.y, c4.y);

      vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z),
                  'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(',
                  filter.join(''), ", sizingmethod='clip');")
    } else {
      vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;');
    }

    vmlStr.push(' ">' ,
                '<g_vml_:image src="', image.src, '"',
                ' style="width:', Z * dw, 'px;',
                ' height:', Z * dh, 'px;"',
                ' cropleft="', sx / w, '"',
                ' croptop="', sy / h, '"',
                ' cropright="', (w - sx - sw) / w, '"',
                ' cropbottom="', (h - sy - sh) / h, '"',
                ' />',
                '</g_vml_:group>');

    this.element_.insertAdjacentHTML('BeforeEnd',
                                    vmlStr.join(''));
  };

  contextPrototype.stroke = function(aFill) {
    var lineStr = [];
    var lineOpen = false;
    var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
    var color = a.color;
    var opacity = a.alpha * this.globalAlpha;

    var W = 10;
    var H = 10;

    lineStr.push('<g_vml_:shape',
                 ' filled="', !!aFill, '"',
                 ' style="position:absolute;width:', W, 'px;height:', H, 'px;"',
                 ' coordorigin="0 0" coordsize="', Z * W, ' ', Z * H, '"',
                 ' stroked="', !aFill, '"',
                 ' path="');

    var newSeq = false;
    var min = {x: null, y: null};
    var max = {x: null, y: null};

    for (var i = 0; i < this.currentPath_.length; i++) {
      var p = this.currentPath_[i];
      var c;

      switch (p.type) {
        case 'moveTo':
          c = p;
          lineStr.push(' m ', mr(p.x), ',', mr(p.y));
          break;
        case 'lineTo':
          lineStr.push(' l ', mr(p.x), ',', mr(p.y));
          break;
        case 'close':
          lineStr.push(' x ');
          p = null;
          break;
        case 'bezierCurveTo':
          lineStr.push(' c ',
                       mr(p.cp1x), ',', mr(p.cp1y), ',',
                       mr(p.cp2x), ',', mr(p.cp2y), ',',
                       mr(p.x), ',', mr(p.y));
          break;
        case 'at':
        case 'wa':
          lineStr.push(' ', p.type, ' ',
                       mr(p.x - this.arcScaleX_ * p.radius), ',',
                       mr(p.y - this.arcScaleY_ * p.radius), ' ',
                       mr(p.x + this.arcScaleX_ * p.radius), ',',
                       mr(p.y + this.arcScaleY_ * p.radius), ' ',
                       mr(p.xStart), ',', mr(p.yStart), ' ',
                       mr(p.xEnd), ',', mr(p.yEnd));
          break;
      }


      // TODO: Following is broken for curves due to
      //       move to proper paths.

      // Figure out dimensions so we can do gradient fills
      // properly
      if (p) {
        if (min.x == null || p.x < min.x) {
          min.x = p.x;
        }
        if (max.x == null || p.x > max.x) {
          max.x = p.x;
        }
        if (min.y == null || p.y < min.y) {
          min.y = p.y;
        }
        if (max.y == null || p.y > max.y) {
          max.y = p.y;
        }
      }
    }
    lineStr.push(' ">');

    if (!aFill) {
      var lineWidth = this.lineScale_ * this.lineWidth;

      // VML cannot correctly render a line if the width is less than 1px.
      // In that case, we dilute the color to make the line look thinner.
      if (lineWidth < 1) {
        opacity *= lineWidth;
      }

      lineStr.push(
        '<g_vml_:stroke',
        ' opacity="', opacity, '"',
        ' joinstyle="', this.lineJoin, '"',
        ' miterlimit="', this.miterLimit, '"',
        ' endcap="', processLineCap(this.lineCap), '"',
        ' weight="', lineWidth, 'px"',
        ' color="', color, '" />'
      );
    } else if (typeof this.fillStyle == 'object') {
      var fillStyle = this.fillStyle;
      var angle = 0;
      var focus = {x: 0, y: 0};

      // additional offset
      var shift = 0;
      // scale factor for offset
      var expansion = 1;

      if (fillStyle.type_ == 'gradient') {
        var x0 = fillStyle.x0_ / this.arcScaleX_;
        var y0 = fillStyle.y0_ / this.arcScaleY_;
        var x1 = fillStyle.x1_ / this.arcScaleX_;
        var y1 = fillStyle.y1_ / this.arcScaleY_;
        var p0 = this.getCoords_(x0, y0);
        var p1 = this.getCoords_(x1, y1);
        var dx = p1.x - p0.x;
        var dy = p1.y - p0.y;
        angle = Math.atan2(dx, dy) * 180 / Math.PI;

        // The angle should be a non-negative number.
        if (angle < 0) {
          angle += 360;
        }

        // Very small angles produce an unexpected result because they are
        // converted to a scientific notation string.
        if (angle < 1e-6) {
          angle = 0;
        }
      } else {
        var p0 = this.getCoords_(fillStyle.x0_, fillStyle.y0_);
        var width  = max.x - min.x;
        var height = max.y - min.y;
        focus = {
          x: (p0.x - min.x) / width,
          y: (p0.y - min.y) / height
        };

        width  /= this.arcScaleX_ * Z;
        height /= this.arcScaleY_ * Z;
        var dimension = m.max(width, height);
        shift = 2 * fillStyle.r0_ / dimension;
        expansion = 2 * fillStyle.r1_ / dimension - shift;
      }

      // We need to sort the color stops in ascending order by offset,
      // otherwise IE won't interpret it correctly.
      var stops = fillStyle.colors_;
      stops.sort(function(cs1, cs2) {
        return cs1.offset - cs2.offset;
      });

      var length = stops.length;
      var color1 = stops[0].color;
      var color2 = stops[length - 1].color;
      var opacity1 = stops[0].alpha * this.globalAlpha;
      var opacity2 = stops[length - 1].alpha * this.globalAlpha;

      var colors = [];
      for (var i = 0; i < length; i++) {
        var stop = stops[i];
        colors.push(stop.offset * expansion + shift + ' ' + stop.color);
      }

      // When colors attribute is used, the meanings of opacity and o:opacity2
      // are reversed.
      lineStr.push('<g_vml_:fill type="', fillStyle.type_, '"',
                   ' method="none" focus="100%"',
                   ' color="', color1, '"',
                   ' color2="', color2, '"',
                   ' colors="', colors.join(','), '"',
                   ' opacity="', opacity2, '"',
                   ' g_o_:opacity2="', opacity1, '"',
                   ' angle="', angle, '"',
                   ' focusposition="', focus.x, ',', focus.y, '" />');
    } else {
      lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity,
                   '" />');
    }

    lineStr.push('</g_vml_:shape>');

    this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));
  };

  contextPrototype.fill = function() {
    this.stroke(true);
  }

  contextPrototype.closePath = function() {
    this.currentPath_.push({type: 'close'});
  };

  /**
   * @private
   */
  contextPrototype.getCoords_ = function(aX, aY) {
    var m = this.m_;
    return {
      x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2,
      y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2
    }
  };

  contextPrototype.save = function() {
    var o = {};
    copyState(this, o);
    this.aStack_.push(o);
    this.mStack_.push(this.m_);
    this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);
  };

  contextPrototype.restore = function() {
    copyState(this.aStack_.pop(), this);
    this.m_ = this.mStack_.pop();
  };

  function matrixIsFinite(m) {
    for (var j = 0; j < 3; j++) {
      for (var k = 0; k < 2; k++) {
        if (!isFinite(m[j][k]) || isNaN(m[j][k])) {
          return false;
        }
      }
    }
    return true;
  }

  function setM(ctx, m, updateLineScale) {
    if (!matrixIsFinite(m)) {
      return;
    }
    ctx.m_ = m;

    if (updateLineScale) {
      // Get the line scale.
      // Determinant of this.m_ means how much the area is enlarged by the
      // transformation. So its square root can be used as a scale factor
      // for width.
      var det = m[0][0] * m[1][1] - m[0][1] * m[1][0];
      ctx.lineScale_ = sqrt(abs(det));
    }
  }

  contextPrototype.translate = function(aX, aY) {
    var m1 = [
      [1,  0,  0],
      [0,  1,  0],
      [aX, aY, 1]
    ];

    setM(this, matrixMultiply(m1, this.m_), false);
  };

  contextPrototype.rotate = function(aRot) {
    var c = mc(aRot);
    var s = ms(aRot);

    var m1 = [
      [c,  s, 0],
      [-s, c, 0],
      [0,  0, 1]
    ];

    setM(this, matrixMultiply(m1, this.m_), false);
  };

  contextPrototype.scale = function(aX, aY) {
    this.arcScaleX_ *= aX;
    this.arcScaleY_ *= aY;
    var m1 = [
      [aX, 0,  0],
      [0,  aY, 0],
      [0,  0,  1]
    ];

    setM(this, matrixMultiply(m1, this.m_), true);
  };

  contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) {
    var m1 = [
      [m11, m12, 0],
      [m21, m22, 0],
      [dx,  dy,  1]
    ];

    setM(this, matrixMultiply(m1, this.m_), true);
  };

  contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) {
    var m = [
      [m11, m12, 0],
      [m21, m22, 0],
      [dx,  dy,  1]
    ];

    setM(this, m, true);
  };

  /******** STUBS ********/
  contextPrototype.clip = function() {
    // TODO: Implement
  };

  contextPrototype.arcTo = function() {
    // TODO: Implement
  };

  contextPrototype.createPattern = function() {
    return new CanvasPattern_;
  };

  // Gradient / Pattern Stubs
  function CanvasGradient_(aType) {
    this.type_ = aType;
    this.x0_ = 0;
    this.y0_ = 0;
    this.r0_ = 0;
    this.x1_ = 0;
    this.y1_ = 0;
    this.r1_ = 0;
    this.colors_ = [];
  }

  CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
    aColor = processStyle(aColor);
    this.colors_.push({offset: aOffset,
                       color: aColor.color,
                       alpha: aColor.alpha});
  };

  function CanvasPattern_() {}

  // set up externs
  G_vmlCanvasManager = G_vmlCanvasManager_;
  CanvasRenderingContext2D = CanvasRenderingContext2D_;
  CanvasGradient = CanvasGradient_;
  CanvasPattern = CanvasPattern_;

})();

} // if
;/* Copyright (c) 2007 Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * Version: 1.0.2
 * Requires jQuery 1.1.3+
 * Docs: http://docs.jquery.com/Plugins/livequery
 */
(function($){$.extend($.fn,{livequery:function(type,fn,fn2){var self=this,q;if($.isFunction(type))fn2=fn,fn=type,type=undefined;$.each($.livequery.queries,function(i,query){if(self.selector==query.selector&&self.context==query.context&&type==query.type&&(!fn||fn.$lqguid==query.fn.$lqguid)&&(!fn2||fn2.$lqguid==query.fn2.$lqguid))return(q=query)&&false;});q=q||new $.livequery(this.selector,this.context,type,fn,fn2);q.stopped=false;$.livequery.run(q.id);return this;},expire:function(type,fn,fn2){var self=this;if($.isFunction(type))fn2=fn,fn=type,type=undefined;$.each($.livequery.queries,function(i,query){if(self.selector==query.selector&&self.context==query.context&&(!type||type==query.type)&&(!fn||fn.$lqguid==query.fn.$lqguid)&&(!fn2||fn2.$lqguid==query.fn2.$lqguid)&&!this.stopped)$.livequery.stop(query.id);});return this;}});$.livequery=function(selector,context,type,fn,fn2){this.selector=selector;this.context=context||document;this.type=type;this.fn=fn;this.fn2=fn2;this.elements=[];this.stopped=false;this.id=$.livequery.queries.push(this)-1;fn.$lqguid=fn.$lqguid||$.livequery.guid++;if(fn2)fn2.$lqguid=fn2.$lqguid||$.livequery.guid++;return this;};$.livequery.prototype={stop:function(){var query=this;if(this.type)this.elements.unbind(this.type,this.fn);else if(this.fn2)this.elements.each(function(i,el){query.fn2.apply(el);});this.elements=[];this.stopped=true;},run:function(){if(this.stopped)return;var query=this;var oEls=this.elements,els=$(this.selector,this.context),nEls=els.not(oEls);this.elements=els;if(this.type){nEls.bind(this.type,this.fn);if(oEls.length>0)$.each(oEls,function(i,el){if($.inArray(el,els)<0)$.event.remove(el,query.type,query.fn);});}else{nEls.each(function(){query.fn.apply(this);});if(this.fn2&&oEls.length>0)$.each(oEls,function(i,el){if($.inArray(el,els)<0)query.fn2.apply(el);});}}};$.extend($.livequery,{guid:0,queries:[],queue:[],running:false,timeout:null,checkQueue:function(){if($.livequery.running&&$.livequery.queue.length){var length=$.livequery.queue.length;while(length--)$.livequery.queries[$.livequery.queue.shift()].run();}},pause:function(){$.livequery.running=false;},play:function(){$.livequery.running=true;$.livequery.run();},registerPlugin:function(){$.each(arguments,function(i,n){if(!$.fn[n])return;var old=$.fn[n];$.fn[n]=function(){var r=old.apply(this,arguments);$.livequery.run();return r;}});},run:function(id){if(id!=undefined){if($.inArray(id,$.livequery.queue)<0)$.livequery.queue.push(id);}else
$.each($.livequery.queries,function(id){if($.inArray(id,$.livequery.queue)<0)$.livequery.queue.push(id);});if($.livequery.timeout)clearTimeout($.livequery.timeout);$.livequery.timeout=setTimeout($.livequery.checkQueue,20);},stop:function(id){if(id!=undefined)$.livequery.queries[id].stop();else
$.each($.livequery.queries,function(id){$.livequery.queries[id].stop();});}});$.livequery.registerPlugin('append','prepend','after','before','wrap','attr','removeAttr','addClass','removeClass','toggleClass','empty','remove');$(function(){$.livequery.play();});var init=$.prototype.init;$.prototype.init=function(a,c){var r=init.apply(this,arguments);if(a&&a.selector)r.context=a.context,r.selector=a.selector;if(typeof a=='string')r.context=c||document,r.selector=a;return r;};$.prototype.init.prototype=$.prototype;})(jQuery);
/**
 * jCarousel - Riding carousels with jQuery
 *   http://sorgalla.com/jcarousel/
 *
 * Copyright (c) 2006 Jan Sorgalla (http://sorgalla.com)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Built on top of the jQuery library
 *   http://jquery.com
 *
 * Inspired by the "Carousel Component" by Bill Scott
 *   http://billwscott.com/carousel/
 */

(function($) {
    /**
     * Creates a carousel for all matched elements.
     *
     * @example $("#mycarousel").jcarousel();
     * @before <ul id="mycarousel" class="jcarousel-skin-name"><li>First item</li><li>Second item</li></ul>
     * @result
     *
     * <div class="jcarousel-skin-name">
     *   <div class="jcarousel-container">
     *     <div disabled="disabled" class="jcarousel-prev jcarousel-prev-disabled"></div>
     *     <div class="jcarousel-next"></div>
     *     <div class="jcarousel-clip">
     *       <ul class="jcarousel-list">
     *         <li class="jcarousel-item-1">First item</li>
     *         <li class="jcarousel-item-2">Second item</li>
     *       </ul>
     *     </div>
     *   </div>
     * </div>
     *
     * @name jcarousel
     * @type jQuery
     * @param Hash o A set of key/value pairs to set as configuration properties.
     * @cat Plugins/jCarousel
     */
    $.fn.jcarousel = function(o) {
        return this.each(function() {
            new $jc(this, o);
        });
    };

    // Default configuration properties.
    var defaults = {
        vertical: false,
        start: 1,
        offset: 1,
        size: null,
        scroll: 3,
        visible: null,
        animation: 'normal',
        easing: 'swing',
        auto: 0,
        wrap: null,
        initCallback: null,
        reloadCallback: null,
        itemLoadCallback: null,
        itemFirstInCallback: null,
        itemFirstOutCallback: null,
        itemLastInCallback: null,
        itemLastOutCallback: null,
        itemVisibleInCallback: null,
        itemVisibleOutCallback: null,
        buttonNextHTML: '<div></div>',
        buttonPrevHTML: '<div></div>',
        buttonNextEvent: 'click',
        buttonPrevEvent: 'click',
        buttonNextCallback: null,
        buttonPrevCallback: null
    };

    /**
     * The jCarousel object.
     *
     * @constructor
     * @name $.jcarousel
     * @param Object e The element to create the carousel for.
     * @param Hash o A set of key/value pairs to set as configuration properties.
     * @cat Plugins/jCarousel
     */
    $.jcarousel = function(e, o) {
        this.options    = $.extend({}, defaults, o || {});

        this.locked     = false;

        this.container  = null;
        this.clip       = null;
        this.list       = null;
        this.buttonNext = null;
        this.buttonPrev = null;

        this.wh = !this.options.vertical ? 'width' : 'height';
        this.lt = !this.options.vertical ? 'left' : 'top';

        // Extract skin class
        var skin = '', split = e.className.split(' ');

        for (var i = 0; i < split.length; i++) {
            if (split[i].indexOf('jcarousel-skin') != -1) {
                $(e).removeClass(split[i]);
                var skin = split[i];
                break;
            }
        }

        if (e.nodeName == 'UL' || e.nodeName == 'OL') {
            this.list = $(e);
            this.container = this.list.parent();

            if (this.container.hasClass('jcarousel-clip')) {
                if (!this.container.parent().hasClass('jcarousel-container'))
                    this.container = this.container.wrap('<div></div>');

                this.container = this.container.parent();
            } else if (!this.container.hasClass('jcarousel-container'))
                this.container = this.list.wrap('<div></div>').parent();
        } else {
            this.container = $(e);
            this.list = $(e).find('>ul,>ol,div>ul,div>ol');
        }

        if (skin != '' && this.container.parent()[0].className.indexOf('jcarousel-skin') == -1)
        	this.container.wrap('<div class=" '+ skin + '"></div>');

        this.clip = this.list.parent();

        if (!this.clip.length || !this.clip.hasClass('jcarousel-clip'))
            this.clip = this.list.wrap('<div></div>').parent();

        this.buttonPrev = $('.jcarousel-prev', this.container);

        if (this.buttonPrev.size() == 0 && this.options.buttonPrevHTML != null)
            this.buttonPrev = this.clip.before(this.options.buttonPrevHTML).prev();

        this.buttonPrev.addClass(this.className('jcarousel-prev'));

        this.buttonNext = $('.jcarousel-next', this.container);

        if (this.buttonNext.size() == 0 && this.options.buttonNextHTML != null)
            this.buttonNext = this.clip.before(this.options.buttonNextHTML).prev();

        this.buttonNext.addClass(this.className('jcarousel-next'));

        this.clip.addClass(this.className('jcarousel-clip'));
        this.list.addClass(this.className('jcarousel-list'));
        this.container.addClass(this.className('jcarousel-container'));

        var di = this.options.visible != null ? Math.ceil(this.clipping() / this.options.visible) : null;
        var li = this.list.children('li');

        var self = this;

        if (li.size() > 0) {
            var wh = 0, i = this.options.offset;
            li.each(function() {
                self.format(this, i++);
                wh += self.dimension(this, di);
            });

            this.list.css(this.wh, wh + 'px');

            // Only set if not explicitly passed as option
            if (!o || o.size === undefined)
                this.options.size = li.size();
        }

        // For whatever reason, .show() does not work in Safari...
        this.container.css('display', 'block');
        this.buttonNext.css('display', 'block');
        this.buttonPrev.css('display', 'block');

        this.funcNext   = function() { self.next(); };
        this.funcPrev   = function() { self.prev(); };
        this.funcResize = function() { self.reload(); };

        if (this.options.initCallback != null)
            this.options.initCallback(this, 'init');

        if ($.browser.safari) {
            this.buttons(false, false);
            $(window).bind('load', function() { self.setup(); });
        } else
            this.setup();
    };

    // Create shortcut for internal use
    var $jc = $.jcarousel;

    $jc.fn = $jc.prototype = {
        jcarousel: '0.2.3'
    };

    $jc.fn.extend = $jc.extend = $.extend;

    $jc.fn.extend({
        /**
         * Setups the carousel.
         *
         * @name setup
         * @type undefined
         * @cat Plugins/jCarousel
         */
        setup: function() {
            this.first     = null;
            this.last      = null;
            this.prevFirst = null;
            this.prevLast  = null;
            this.animating = false;
            this.timer     = null;
            this.tail      = null;
            this.inTail    = false;

            if (this.locked)
                return;

            this.list.css(this.lt, this.pos(this.options.offset) + 'px');
            var p = this.pos(this.options.start);
            this.prevFirst = this.prevLast = null;
            this.animate(p, false);

            $(window).unbind('resize', this.funcResize).bind('resize', this.funcResize);
        },

        /**
         * Clears the list and resets the carousel.
         *
         * @name reset
         * @type undefined
         * @cat Plugins/jCarousel
         */
        reset: function() {
            this.list.empty();

            this.list.css(this.lt, '0px');
            this.list.css(this.wh, '10px');

            if (this.options.initCallback != null)
                this.options.initCallback(this, 'reset');

            this.setup();
        },

        /**
         * Reloads the carousel and adjusts positions.
         *
         * @name reload
         * @type undefined
         * @cat Plugins/jCarousel
         */
        reload: function() {
            if (this.tail != null && this.inTail)
                this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) + this.tail);

            this.tail   = null;
            this.inTail = false;

            if (this.options.reloadCallback != null)
                this.options.reloadCallback(this);

            if (this.options.visible != null) {
                var self = this;
                var di = Math.ceil(this.clipping() / this.options.visible), wh = 0, lt = 0;
                $('li', this.list).each(function(i) {
                    wh += self.dimension(this, di);
                    if (i + 1 < self.first)
                        lt = wh;
                });

                this.list.css(this.wh, wh + 'px');
                this.list.css(this.lt, -lt + 'px');
            }

            this.scroll(this.first, false);
        },

        /**
         * Locks the carousel.
         *
         * @name lock
         * @type undefined
         * @cat Plugins/jCarousel
         */
        lock: function() {
            this.locked = true;
            this.buttons();
        },

        /**
         * Unlocks the carousel.
         *
         * @name unlock
         * @type undefined
         * @cat Plugins/jCarousel
         */
        unlock: function() {
            this.locked = false;
            this.buttons();
        },

        /**
         * Sets the size of the carousel.
         *
         * @name size
         * @type undefined
         * @param Number s The size of the carousel.
         * @cat Plugins/jCarousel
         */
        size: function(s) {
            if (s != undefined) {
                this.options.size = s;
                if (!this.locked)
                    this.buttons();
            }

            return this.options.size;
        },

        /**
         * Checks whether a list element exists for the given index (or index range).
         *
         * @name get
         * @type bool
         * @param Number i The index of the (first) element.
         * @param Number i2 The index of the last element.
         * @cat Plugins/jCarousel
         */
        has: function(i, i2) {
            if (i2 == undefined || !i2)
                i2 = i;

            if (this.options.size !== null && i2 > this.options.size)
            	i2 = this.options.size;

            for (var j = i; j <= i2; j++) {
                var e = this.get(j);
                if (!e.length || e.hasClass('jcarousel-item-placeholder'))
                    return false;
            }

            return true;
        },

        /**
         * Returns a jQuery object with list element for the given index.
         *
         * @name get
         * @type jQuery
         * @param Number i The index of the element.
         * @cat Plugins/jCarousel
         */
        get: function(i) {
            return $('.jcarousel-item-' + i, this.list);
        },

        /**
         * Adds an element for the given index to the list.
         * If the element already exists, it updates the inner html.
         * Returns the created element as jQuery object.
         *
         * @name add
         * @type jQuery
         * @param Number i The index of the element.
         * @param String s The innerHTML of the element.
         * @cat Plugins/jCarousel
         */
        add: function(i, s) {
            var e = this.get(i), old = 0, add = 0;

            if (e.length == 0) {
                var c, e = this.create(i), j = $jc.intval(i);
                while (c = this.get(--j)) {
                    if (j <= 0 || c.length) {
                        j <= 0 ? this.list.prepend(e) : c.after(e);
                        break;
                    }
                }
            } else
                old = this.dimension(e);

            e.removeClass(this.className('jcarousel-item-placeholder'));
            typeof s == 'string' ? e.html(s) : e.empty().append(s);

            var di = this.options.visible != null ? Math.ceil(this.clipping() / this.options.visible) : null;
            var wh = this.dimension(e, di) - old;

            if (i > 0 && i < this.first)
                this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) - wh + 'px');

            this.list.css(this.wh, $jc.intval(this.list.css(this.wh)) + wh + 'px');

            return e;
        },

        /**
         * Removes an element for the given index from the list.
         *
         * @name remove
         * @type undefined
         * @param Number i The index of the element.
         * @cat Plugins/jCarousel
         */
        remove: function(i) {
            var e = this.get(i);

            // Check if item exists and is not currently visible
            if (!e.length || (i >= this.first && i <= this.last))
                return;

            var d = this.dimension(e);

            if (i < this.first)
                this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) + d + 'px');

            e.remove();

            this.list.css(this.wh, $jc.intval(this.list.css(this.wh)) - d + 'px');
        },

        /**
         * Moves the carousel forwards.
         *
         * @name next
         * @type undefined
         * @cat Plugins/jCarousel
         */
        next: function() {
            this.stopAuto();

            if (this.tail != null && !this.inTail)
                this.scrollTail(false);
            else
                this.scroll(((this.options.wrap == 'both' || this.options.wrap == 'last') && this.options.size != null && this.last == this.options.size) ? 1 : this.first + this.options.scroll);
        },

        /**
         * Moves the carousel backwards.
         *
         * @name prev
         * @type undefined
         * @cat Plugins/jCarousel
         */
        prev: function() {
            this.stopAuto();

            if (this.tail != null && this.inTail)
                this.scrollTail(true);
            else
                this.scroll(((this.options.wrap == 'both' || this.options.wrap == 'first') && this.options.size != null && this.first == 1) ? this.options.size : this.first - this.options.scroll);
        },

        /**
         * Scrolls the tail of the carousel.
         *
         * @name scrollTail
         * @type undefined
         * @param Bool b Whether scroll the tail back or forward.
         * @cat Plugins/jCarousel
         */
        scrollTail: function(b) {
            if (this.locked || this.animating || !this.tail)
                return;

            var pos  = $jc.intval(this.list.css(this.lt));

            !b ? pos -= this.tail : pos += this.tail;
            this.inTail = !b;

            // Save for callbacks
            this.prevFirst = this.first;
            this.prevLast  = this.last;

            this.animate(pos);
        },

        /**
         * Scrolls the carousel to a certain position.
         *
         * @name scroll
         * @type undefined
         * @param Number i The index of the element to scoll to.
         * @param Bool a Flag indicating whether to perform animation.
         * @cat Plugins/jCarousel
         */
        scroll: function(i, a) {
            if (this.locked || this.animating)
                return;

            this.animate(this.pos(i), a);
        },

        /**
         * Prepares the carousel and return the position for a certian index.
         *
         * @name pos
         * @type Number
         * @param Number i The index of the element to scoll to.
         * @cat Plugins/jCarousel
         */
        pos: function(i) {
            if (this.locked || this.animating)
                return;

            if (this.options.wrap != 'circular')
                i = i < 1 ? 1 : (this.options.size && i > this.options.size ? this.options.size : i);

            var back = this.first > i;
            var pos  = $jc.intval(this.list.css(this.lt));

            // Create placeholders, new list width/height
            // and new list position
            var f = this.options.wrap != 'circular' && this.first <= 1 ? 1 : this.first;
            var c = back ? this.get(f) : this.get(this.last);
            var j = back ? f : f - 1;
            var e = null, l = 0, p = false, d = 0;

            while (back ? --j >= i : ++j < i) {
                e = this.get(j);
                p = !e.length;
                if (e.length == 0) {
                    e = this.create(j).addClass(this.className('jcarousel-item-placeholder'));
                    c[back ? 'before' : 'after' ](e);
                }

                c = e;
                d = this.dimension(e);

                if (p)
                    l += d;

                if (this.first != null && (this.options.wrap == 'circular' || (j >= 1 && (this.options.size == null || j <= this.options.size))))
                    pos = back ? pos + d : pos - d;
            }

            // Calculate visible items
            var clipping = this.clipping();
            var cache = [];
            var visible = 0, j = i, v = 0;
            var c = this.get(i - 1);

            while (++visible) {
                e = this.get(j);
                p = !e.length;
                if (e.length == 0) {
                    e = this.create(j).addClass(this.className('jcarousel-item-placeholder'));
                    // This should only happen on a next scroll
                    c.length == 0 ? this.list.prepend(e) : c[back ? 'before' : 'after' ](e);
                }

                c = e;
                var d = this.dimension(e);
                if (d == 0) {
                    //alert('jCarousel: No width/height set for items. This will cause an infinite loop. Aborting...');
                    return 0;
                }

                if (this.options.wrap != 'circular' && this.options.size !== null && j > this.options.size)
                    cache.push(e);
                else if (p)
                    l += d;

                v += d;

                if (v >= clipping)
                    break;

                j++;
            }

             // Remove out-of-range placeholders
            for (var x = 0; x < cache.length; x++)
                cache[x].remove();

            // Resize list
            if (l > 0) {
                this.list.css(this.wh, this.dimension(this.list) + l + 'px');

                if (back) {
                    pos -= l;
                    this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) - l + 'px');
                }
            }

            // Calculate first and last item
            var last = i + visible - 1;
            if (this.options.wrap != 'circular' && this.options.size && last > this.options.size)
                last = this.options.size;

            if (j > last) {
                visible = 0, j = last, v = 0;
                while (++visible) {
                    var e = this.get(j--);
                    if (!e.length)
                        break;
                    v += this.dimension(e);
                    if (v >= clipping)
                        break;
                }
            }

            var first = last - visible + 1;
            if (this.options.wrap != 'circular' && first < 1)
                first = 1;

            if (this.inTail && back) {
                pos += this.tail;
                this.inTail = false;
            }

            this.tail = null;
            if (this.options.wrap != 'circular' && last == this.options.size && (last - visible + 1) >= 1) {
                var m = $jc.margin(this.get(last), !this.options.vertical ? 'marginRight' : 'marginBottom');
                if ((v - m) > clipping)
                    this.tail = v - clipping - m;
            }

            // Adjust position
            while (i-- > first)
                pos += this.dimension(this.get(i));

            // Save visible item range
            this.prevFirst = this.first;
            this.prevLast  = this.last;
            this.first     = first;
            this.last      = last;

            return pos;
        },

        /**
         * Animates the carousel to a certain position.
         *
         * @name animate
         * @type undefined
         * @param mixed p Position to scroll to.
         * @param Bool a Flag indicating whether to perform animation.
         * @cat Plugins/jCarousel
         */
        animate: function(p, a) {
            if (this.locked || this.animating)
                return;

            this.animating = true;

            var self = this;
            var scrolled = function() {
                self.animating = false;

                if (p == 0)
                    self.list.css(self.lt,  0);

                if (self.options.wrap == 'both' || self.options.wrap == 'last' || self.options.size == null || self.last < self.options.size)
                    self.startAuto();

                self.buttons();
                self.notify('onAfterAnimation');
            };

            this.notify('onBeforeAnimation');

            // Animate
            if (!this.options.animation || a == false) {
                this.list.css(this.lt, p + 'px');
                scrolled();
            } else {
                var o = !this.options.vertical ? {'left': p} : {'top': p};
                this.list.animate(o, this.options.animation, this.options.easing, scrolled);
            }
        },

        /**
         * Starts autoscrolling.
         *
         * @name auto
         * @type undefined
         * @param Number s Seconds to periodically autoscroll the content.
         * @cat Plugins/jCarousel
         */
        startAuto: function(s) {
            if (s != undefined)
                this.options.auto = s;

            if (this.options.auto == 0)
                return this.stopAuto();

            if (this.timer != null)
                return;

            var self = this;
            this.timer = setTimeout(function() { self.next(); }, this.options.auto * 1000);
        },

        /**
         * Stops autoscrolling.
         *
         * @name stopAuto
         * @type undefined
         * @cat Plugins/jCarousel
         */
        stopAuto: function() {
            if (this.timer == null)
                return;

            clearTimeout(this.timer);
            this.timer = null;
        },

        /**
         * Sets the states of the prev/next buttons.
         *
         * @name buttons
         * @type undefined
         * @cat Plugins/jCarousel
         */
        buttons: function(n, p) {
            if (n == undefined || n == null) {
                var n = !this.locked && this.options.size !== 0 && ((this.options.wrap && this.options.wrap != 'first') || this.options.size == null || this.last < this.options.size);
                if (!this.locked && (!this.options.wrap || this.options.wrap == 'first') && this.options.size != null && this.last >= this.options.size)
                    n = this.tail != null && !this.inTail;
            }

            if (p == undefined || p == null) {
                var p = !this.locked && this.options.size !== 0 && ((this.options.wrap && this.options.wrap != 'last') || this.first > 1);
                if (!this.locked && (!this.options.wrap || this.options.wrap == 'last') && this.options.size != null && this.first == 1)
                    p = this.tail != null && this.inTail;
            }

            var self = this;

            this.buttonNext[n ? 'bind' : 'unbind'](this.options.buttonNextEvent, this.funcNext)[n ? 'removeClass' : 'addClass'](this.className('jcarousel-next-disabled')).attr('disabled', n ? false : true);
            this.buttonPrev[p ? 'bind' : 'unbind'](this.options.buttonPrevEvent, this.funcPrev)[p ? 'removeClass' : 'addClass'](this.className('jcarousel-prev-disabled')).attr('disabled', p ? false : true);

            if (this.buttonNext.length > 0 && (this.buttonNext[0].jcarouselstate == undefined || this.buttonNext[0].jcarouselstate != n) && this.options.buttonNextCallback != null) {
                this.buttonNext.each(function() { self.options.buttonNextCallback(self, this, n); });
                this.buttonNext[0].jcarouselstate = n;
            }

            if (this.buttonPrev.length > 0 && (this.buttonPrev[0].jcarouselstate == undefined || this.buttonPrev[0].jcarouselstate != p) && this.options.buttonPrevCallback != null) {
                this.buttonPrev.each(function() { self.options.buttonPrevCallback(self, this, p); });
                this.buttonPrev[0].jcarouselstate = p;
            }
        },

        notify: function(evt) {
            var state = this.prevFirst == null ? 'init' : (this.prevFirst < this.first ? 'next' : 'prev');

            // Load items
            this.callback('itemLoadCallback', evt, state);

            if (this.prevFirst !== this.first) {
                this.callback('itemFirstInCallback', evt, state, this.first);
                this.callback('itemFirstOutCallback', evt, state, this.prevFirst);
            }

            if (this.prevLast !== this.last) {
                this.callback('itemLastInCallback', evt, state, this.last);
                this.callback('itemLastOutCallback', evt, state, this.prevLast);
            }

            this.callback('itemVisibleInCallback', evt, state, this.first, this.last, this.prevFirst, this.prevLast);
            this.callback('itemVisibleOutCallback', evt, state, this.prevFirst, this.prevLast, this.first, this.last);
        },

        callback: function(cb, evt, state, i1, i2, i3, i4) {
            if (this.options[cb] == undefined || (typeof this.options[cb] != 'object' && evt != 'onAfterAnimation'))
                return;

            var callback = typeof this.options[cb] == 'object' ? this.options[cb][evt] : this.options[cb];

            if (!$.isFunction(callback))
                return;

            var self = this;

            if (i1 === undefined)
                callback(self, state, evt);
            else if (i2 === undefined)
                this.get(i1).each(function() { callback(self, this, i1, state, evt); });
            else {
                for (var i = i1; i <= i2; i++)
                    if (i !== null && !(i >= i3 && i <= i4))
                        this.get(i).each(function() { callback(self, this, i, state, evt); });
            }
        },

        create: function(i) {
            return this.format('<li></li>', i);
        },

        format: function(e, i) {
            var $e = $(e).addClass(this.className('jcarousel-item')).addClass(this.className('jcarousel-item-' + i));
            $e.attr('jcarouselindex', i);
            return $e;
        },

        className: function(c) {
            return c + ' ' + c + (!this.options.vertical ? '-horizontal' : '-vertical');
        },

        dimension: function(e, d) {
            var el = e.jquery != undefined ? e[0] : e;

            var old = !this.options.vertical ?
                el.offsetWidth + $jc.margin(el, 'marginLeft') + $jc.margin(el, 'marginRight') :
                el.offsetHeight + $jc.margin(el, 'marginTop') + $jc.margin(el, 'marginBottom');

            if (d == undefined || old == d)
                return old;

            var w = !this.options.vertical ?
                d - $jc.margin(el, 'marginLeft') - $jc.margin(el, 'marginRight') :
                d - $jc.margin(el, 'marginTop') - $jc.margin(el, 'marginBottom');

            $(el).css(this.wh, w + 'px');

            return this.dimension(el);
        },

        clipping: function() {
            return !this.options.vertical ?
                this.clip[0].offsetWidth - $jc.intval(this.clip.css('borderLeftWidth')) - $jc.intval(this.clip.css('borderRightWidth')) :
                this.clip[0].offsetHeight - $jc.intval(this.clip.css('borderTopWidth')) - $jc.intval(this.clip.css('borderBottomWidth'));
        },

        index: function(i, s) {
            if (s == undefined)
                s = this.options.size;

            return Math.round((((i-1) / s) - Math.floor((i-1) / s)) * s) + 1;
        }
    });

    $jc.extend({
        /**
         * Gets/Sets the global default configuration properties.
         *
         * @name defaults
         * @descr Gets/Sets the global default configuration properties.
         * @type Hash
         * @param Hash d A set of key/value pairs to set as configuration properties.
         * @cat Plugins/jCarousel
         */
        defaults: function(d) {
            return $.extend(defaults, d || {});
        },

        margin: function(e, p) {
            if (!e)
                return 0;

            var el = e.jquery != undefined ? e[0] : e;

            if (p == 'marginRight' && $.browser.safari) {
                var old = {'display': 'block', 'float': 'none', 'width': 'auto'}, oWidth, oWidth2;

                $.swap(el, old, function() { oWidth = el.offsetWidth; });

                old['marginRight'] = 0;
                $.swap(el, old, function() { oWidth2 = el.offsetWidth; });

                return oWidth2 - oWidth;
            }

            return $jc.intval($.css(el, p));
        },

        intval: function(v) {
            v = parseInt(v);
            return isNaN(v) ? 0 : v;
        }
    });

})(jQuery);
/*
 * @name BeautyTips
 * @desc a tooltips/baloon-help plugin for jQuery
 *
 * @author Jeff Robbins - Lullabot - http://www.lullabot.com
 * @version 0.9.5 release candidate 1  (5/20/2009)
 */
 
jQuery.bt = {version: '0.9.5-rc1'};
 
/*
 * @type jQuery
 * @cat Plugins/bt
 * @requires jQuery v1.2+ (not tested on versions prior to 1.2.6)
 *
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Encourage development. If you use BeautyTips for anything cool 
 * or on a site that people have heard of, please drop me a note.
 * - jeff ^at lullabot > com
 *
 * No guarantees, warranties, or promises of any kind
 *
 */

;(function($) { 
  /**
   * @credit Inspired by Karl Swedberg's ClueTip
   *    (http://plugins.learningjquery.com/cluetip/), which in turn was inspired
   *    by Cody Lindley's jTip (http://www.codylindley.com)
   *
   * @fileoverview
   * Beauty Tips is a jQuery tooltips plugin which uses the canvas drawing element
   * in the HTML5 spec in order to dynamically draw tooltip "talk bubbles" around
   * the descriptive help text associated with an item. This is in many ways
   * similar to Google Maps which both provides similar talk-bubbles and uses the
   * canvas element to draw them.
   *
   * The canvas element is supported in modern versions of FireFox, Safari, and
   * Opera. However, Internet Explorer needs a separate library called ExplorerCanvas
   * included on the page in order to support canvas drawing functions. ExplorerCanvas
   * was created by Google for use with their web apps and you can find it here:
   * http://excanvas.sourceforge.net/
   *
   * Beauty Tips was written to be simple to use and pretty. All of its options
   * are documented at the bottom of this file and defaults can be overwritten
   * globally for the entire page, or individually on each call.
   *
   * By default each tooltip will be positioned on the side of the target element
   * which has the most free space. This is affected by the scroll position and
   * size of the current window, so each Beauty Tip is redrawn each time it is
   * displayed. It may appear above an element at the bottom of the page, but when
   * the page is scrolled down (and the element is at the top of the page) it will
   * then appear below it. Additionally, positions can be forced or a preferred
   * order can be defined. See examples below.
   *
   * To fix z-index problems in IE6, include the bgiframe plugin on your page
   * http://plugins.jquery.com/project/bgiframe - BeautyTips will automatically
   * recognize it and use it.
   *
   * BeautyTips also works with the hoverIntent plugin
   * http://cherne.net/brian/resources/jquery.hoverIntent.html
   * see hoverIntent example below for usage
   *
   * Usage
   * The function can be called in a number of ways.
   * $(selector).bt();
   * $(selector).bt('Content text');
   * $(selector).bt('Content text', {option1: value, option2: value});
   * $(selector).bt({option1: value, option2: value});
   *
   * For more/better documentation and lots of examples, visit the demo page included with the distribution
   *
   */ 
  
  jQuery.fn.bt = function(content, options) {
  
    if (typeof content != 'string') {
      var contentSelect = true;
      options = content;
      content = false;
    }
    else {
      var contentSelect = false;
    }
    
    // if hoverIntent is installed, use that as default instead of hover
    if (jQuery.fn.hoverIntent && jQuery.bt.defaults.trigger == 'hover') {
      jQuery.bt.defaults.trigger = 'hoverIntent';
    }
  
    return this.each(function(index) {
  
      var opts = jQuery.extend(false, jQuery.bt.defaults, jQuery.bt.options, options);
  
      // clean up the options
      opts.spikeLength = numb(opts.spikeLength);
      opts.spikeGirth = numb(opts.spikeGirth);
      opts.overlap = numb(opts.overlap);
      
      var ajaxTimeout = false;
      
      /**
       * This is sort of the "starting spot" for the this.each()
       * These are the init functions to handle the .bt() call
       */
  
      if (opts.killTitle) {
        $(this).find('[title]').andSelf().each(function() {
          if (!$(this).attr('bt-xTitle')) {
            $(this).attr('bt-xTitle', $(this).attr('title')).attr('title', '');
          }
        });
      }    
      
      if (typeof opts.trigger == 'string') {
        opts.trigger = [opts.trigger];
      }
      if (opts.trigger[0] == 'hoverIntent') {
        var hoverOpts = jQuery.extend(opts.hoverIntentOpts, {
          over: function() {
            this.btOn();
          },
          out: function() {
            this.btOff();
          }});
        $(this).hoverIntent(hoverOpts);
      
      }
      else if (opts.trigger[0] == 'hover') {
        $(this).hover(
          function() {
            this.btOn();
          },
          function() {
            this.btOff();
          }
        );
      }
      else if (opts.trigger[0] == 'now') {
        // toggle the on/off right now
        // note that 'none' gives more control (see below)
        if ($(this).hasClass('bt-active')) {
          this.btOff();
        }
        else {
          this.btOn();
        }
      }
      else if (opts.trigger[0] == 'none') {
        // initialize the tip with no event trigger
        // use javascript to turn on/off tip as follows:
        // $('#selector').btOn();
        // $('#selector').btOff();
      }
      else if (opts.trigger.length > 1 && opts.trigger[0] != opts.trigger[1]) {
        $(this)
          .bind(opts.trigger[0], function() {
            this.btOn();
          })
          .bind(opts.trigger[1], function() {
            this.btOff();
          });
      }
      else {
        // toggle using the same event
        $(this).bind(opts.trigger[0], function() {
          if ($(this).hasClass('bt-active')) {
            this.btOff();
          }
          else {
            this.btOn();
          }
        });
      }
      
      
      /**
       *  The BIG TURN ON
       *  Any element that has been initiated
       */
      this.btOn = function () {
        if (typeof $(this).data('bt-box') == 'object') {
          // if there's already a popup, remove it before creating a new one.
          this.btOff();
        }
  
        // trigger preBuild function
        // preBuild has no argument since the box hasn't been built yet
        opts.preBuild.apply(this);
        
        // turn off other tips
        $(jQuery.bt.vars.closeWhenOpenStack).btOff();
        
        // add the class to the target element (for hilighting, for example)
        // bt-active is always applied to all, but activeClass can apply another
        $(this).addClass('bt-active ' + opts.activeClass);
  
        if (contentSelect && opts.ajaxPath == null) {
          // bizarre, I know
          if (opts.killTitle) {
            // if we've killed the title attribute, it's been stored in 'bt-xTitle' so get it..
            $(this).attr('title', $(this).attr('bt-xTitle'));
          }
          // then evaluate the selector... title is now in place
          content = $.isFunction(opts.contentSelector) ? opts.contentSelector.apply(this) : eval(opts.contentSelector);
          if (opts.killTitle) {
            // now remove the title again, so we don't get double tips
            $(this).attr('title', '');
          }
        }
        
        // ----------------------------------------------
        // All the Ajax(ish) stuff is in this next bit...
        // ----------------------------------------------
        if (opts.ajaxPath != null && content == false) {
          if (typeof opts.ajaxPath == 'object') {
            var url = eval(opts.ajaxPath[0]);
            url += opts.ajaxPath[1] ? ' ' + opts.ajaxPath[1] : '';
          }
          else {
            var url = opts.ajaxPath;
          }
          var off = url.indexOf(" ");
          if ( off >= 0 ) {
            var selector = url.slice(off, url.length);
            url = url.slice(0, off);
          }
        
          // load any data cached for the given ajax path
          var cacheData = opts.ajaxCache ? $(document.body).data('btCache-' + url.replace(/\./g, '')) : null;
          if (typeof cacheData == 'string') {
            content = selector ? $("<div/>").append(cacheData.replace(/<script(.|\s)*?\/script>/g, "")).find(selector) : cacheData;
          }
          else {
            var target = this;
                      
            // set up the options
            var ajaxOpts = jQuery.extend(false,
            {
              type: opts.ajaxType,
              data: opts.ajaxData,
              cache: opts.ajaxCache,
              url: url,
              complete: function(XMLHttpRequest, textStatus) {
                if (textStatus == 'success' || textStatus == 'notmodified') {
                  if (opts.ajaxCache) {
                    $(document.body).data('btCache-' + url.replace(/\./g, ''), XMLHttpRequest.responseText);
                  }
                  ajaxTimeout = false;
                  content = selector ?
                    // Create a dummy div to hold the results
                    $("<div/>")
                      // inject the contents of the document in, removing the scripts
                      // to avoid any 'Permission Denied' errors in IE
                      .append(XMLHttpRequest.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
        
                      // Locate the specified elements
                      .find(selector) :
        
                    // If not, just inject the full result
                    XMLHttpRequest.responseText;
                   
                }
                else {
                  if (textStatus == 'timeout') {
                    // if there was a timeout, we don't cache the result
                    ajaxTimeout = true;
                  }
                  content = opts.ajaxError.replace(/%error/g, XMLHttpRequest.statusText);
                }
                // if the user rolls out of the target element before the ajax request comes back, don't show it
                if ($(target).hasClass('bt-active')) {
                  target.btOn();
                }
              }
            }, opts.ajaxOpts);
            // do the ajax request
            jQuery.ajax(ajaxOpts);
            // load the throbber while the magic happens
            content = opts.ajaxLoading;
          }
        }
        // </ ajax stuff >
        
  
        // now we start actually figuring out where to place the tip
        
        // figure out how to compensate for the shadow, if present
        var shadowMarginX = 0; // extra added to width to compensate for shadow
        var shadowMarginY = 0; // extra added to height
        var shadowShiftX = 0;  // amount to shift the tip horizontally to allow for shadow
        var shadowShiftY = 0;  // amount to shift vertical
        
        if (opts.shadow && !shadowSupport()) {
          // if browser doesn't support drop shadows, turn them off
          opts.shadow = false;
          // and bring in the noShadows options
          jQuery.extend(opts, opts.noShadowOpts);
        }
        
        if (opts.shadow) {
          // figure out horizontal placement
          if (opts.shadowBlur > Math.abs(opts.shadowOffsetX)) {
            shadowMarginX = opts.shadowBlur * 2;
          }
          else {
            shadowMarginX = opts.shadowBlur + Math.abs(opts.shadowOffsetX);
          }
          shadowShiftX = (opts.shadowBlur - opts.shadowOffsetX) > 0 ? opts.shadowBlur - opts.shadowOffsetX : 0;
          
          // now vertical
          if (opts.shadowBlur > Math.abs(opts.shadowOffsetY)) {
            shadowMarginY = opts.shadowBlur * 2;
          }
          else {
            shadowMarginY = opts.shadowBlur + Math.abs(opts.shadowOffsetY);
          }
          shadowShiftY = (opts.shadowBlur - opts.shadowOffsetY) > 0 ? opts.shadowBlur - opts.shadowOffsetY : 0;
        }
        
        if (opts.offsetParent){
          // if offsetParent is defined by user
          var offsetParent = $(opts.offsetParent);
          var offsetParentPos = offsetParent.offset();
          var pos = $(this).offset();
          var top = numb(pos.top) - numb(offsetParentPos.top) + numb($(this).css('margin-top')) - shadowShiftY; // IE can return 'auto' for margins
          var left = numb(pos.left) - numb(offsetParentPos.left) + numb($(this).css('margin-left')) - shadowShiftX;
        }
        else {
          // if the target element is absolutely positioned, use its parent's offsetParent instead of its own
          var offsetParent = ($(this).css('position') == 'absolute') ? $(this).parents().eq(0).offsetParent() : $(this).offsetParent();
          var pos = $(this).btPosition();
          var top = numb(pos.top) + numb($(this).css('margin-top')) - shadowShiftY; // IE can return 'auto' for margins
          var left = numb(pos.left) + numb($(this).css('margin-left')) - shadowShiftX;
        }

        var width = $(this).btOuterWidth();
        var height = $(this).outerHeight();
        
        if (typeof content == 'object') {
          // if content is a DOM object (as opposed to text)
          // use a clone, rather than removing the original element
          // and ensure that it's visible
          var original = content;
          var clone = $(original).clone(true).show();
          // also store a reference to the original object in the clone data
          // and a reference to the clone in the original
          var origClones = $(original).data('bt-clones') || [];
          origClones.push(clone);
          $(original).data('bt-clones', origClones);
          $(clone).data('bt-orig', original);
          $(this).data('bt-content-orig', {original: original, clone: clone});
          content = clone;
        }
        if (typeof content == 'null' || content == '') {
          // if content is empty, bail out...
          return;
        }
        
        // create the tip content div, populate it, and style it
        var $text = $('<div class="bt-content"></div>').append(content).css({padding: opts.padding, position: 'absolute', width: (opts.shrinkToFit ? 'auto' : opts.width), zIndex: opts.textzIndex, left: shadowShiftX, top: shadowShiftY}).css(opts.cssStyles);
        // create the wrapping box which contains text and canvas
        // put the content in it, style it, and append it to the same offset parent as the target
        var $box = $('<div class="bt-wrapper"></div>').append($text).addClass(opts.cssClass).css({position: 'absolute', width: opts.width, zIndex: opts.wrapperzIndex, visibility:'hidden'}).appendTo(offsetParent);
        
        // use bgiframe to get around z-index problems in IE6
        // http://plugins.jquery.com/project/bgiframe
        if (jQuery.fn.bgiframe) {
          $text.bgiframe();
          $box.bgiframe();  
        }
  
        $(this).data('bt-box', $box);
  
        // see if the text box will fit in the various positions
        var scrollTop = numb($(document).scrollTop());
        var scrollLeft = numb($(document).scrollLeft());
        var docWidth = numb($(window).width());
        var docHeight = numb($(window).height());
        var winRight = scrollLeft + docWidth;
        var winBottom = scrollTop + docHeight;
        var space = new Object();
        var thisOffset = $(this).offset();
        space.top = thisOffset.top - scrollTop;
        space.bottom = docHeight - ((thisOffset + height) - scrollTop);
        space.left = thisOffset.left - scrollLeft;
        space.right = docWidth - ((thisOffset.left + width) - scrollLeft);
        var textOutHeight = numb($text.outerHeight());
        var textOutWidth = numb($text.btOuterWidth());
        if (opts.positions.constructor == String) {
          opts.positions = opts.positions.replace(/ /, '').split(',');
        }
        if (opts.positions[0] == 'most') {
          // figure out which is the largest
          var position = 'top'; // prime the pump
          for (var pig in space) {  //            <-------  pigs in space!
            position = space[pig] > space[position] ? pig : position;
          }
        }
        else {
          for (var x in opts.positions) {
            var position = opts.positions[x];
            // @todo: acommodate shadow space in the following lines...
            if ((position == 'left' || position == 'right') && space[position] > textOutWidth + opts.spikeLength) {
              break;
            }
            else if ((position == 'top' || position == 'bottom') && space[position] > textOutHeight + opts.spikeLength) {
              break;
            }
          }
        }
  
        // horizontal (left) offset for the box
        var horiz = left + ((width - textOutWidth) * .5);
        // vertical (top) offset for the box
        var vert = top + ((height - textOutHeight) * .5);
        var points = new Array();
        var textTop, textLeft, textRight, textBottom, textTopSpace, textBottomSpace, textLeftSpace, textRightSpace, crossPoint, textCenter, spikePoint;
  
        // Yes, yes, this next bit really could use to be condensed
        // each switch case is basically doing the same thing in slightly different ways
        switch(position) {
          
          // =================== TOP =======================
          case 'top':
            // spike on bottom
            $text.css('margin-bottom', opts.spikeLength + 'px');
            $box.css({top: (top - $text.outerHeight(true)) + opts.overlap, left: horiz});
            // move text left/right if extends out of window
            textRightSpace = (winRight - opts.windowMargin) - ($text.offset().left + $text.btOuterWidth(true));
            var xShift = shadowShiftX;
            if (textRightSpace < 0) {
              // shift it left
              $box.css('left', (numb($box.css('left')) + textRightSpace) + 'px');
              xShift -= textRightSpace;
            }
            // we test left space second to ensure that left of box is visible
            textLeftSpace = ($text.offset().left + numb($text.css('margin-left'))) - (scrollLeft + opts.windowMargin);
            if (textLeftSpace < 0) {
              // shift it right
              $box.css('left', (numb($box.css('left')) - textLeftSpace) + 'px');
              xShift += textLeftSpace;
            }
            textTop = $text.btPosition().top + numb($text.css('margin-top'));
            textLeft = $text.btPosition().left + numb($text.css('margin-left'));
            textRight = textLeft + $text.btOuterWidth();
            textBottom = textTop + $text.outerHeight();
            textCenter = {x: textLeft + ($text.btOuterWidth()*opts.centerPointX), y: textTop + ($text.outerHeight()*opts.centerPointY)};
            // points[points.length] = {x: x, y: y};
            points[points.length] = spikePoint = {y: textBottom + opts.spikeLength, x: ((textRight-textLeft) * .5) + xShift, type: 'spike'};
            crossPoint = findIntersectX(spikePoint.x, spikePoint.y, textCenter.x, textCenter.y, textBottom);
            // make sure that the crossPoint is not outside of text box boundaries
            crossPoint.x = crossPoint.x < textLeft + opts.spikeGirth/2 + opts.cornerRadius ? textLeft + opts.spikeGirth/2 + opts.cornerRadius : crossPoint.x;
            crossPoint.x =  crossPoint.x > (textRight - opts.spikeGirth/2) - opts.cornerRadius ? (textRight - opts.spikeGirth/2) - opts.CornerRadius : crossPoint.x;
            points[points.length] = {x: crossPoint.x - (opts.spikeGirth/2), y: textBottom, type: 'join'};
            points[points.length] = {x: textLeft, y: textBottom, type: 'corner'};  // left bottom corner
            points[points.length] = {x: textLeft, y: textTop, type: 'corner'};     // left top corner
            points[points.length] = {x: textRight, y: textTop, type: 'corner'};    // right top corner
            points[points.length] = {x: textRight, y: textBottom, type: 'corner'}; // right bottom corner
            points[points.length] = {x: crossPoint.x + (opts.spikeGirth/2), y: textBottom, type: 'join'};
            points[points.length] = spikePoint;
            break;
            
          // =================== LEFT =======================
          case 'left':
            // spike on right
            $text.css('margin-right', opts.spikeLength + 'px');
            $box.css({top: vert + 'px', left: ((left - $text.btOuterWidth(true)) + opts.overlap) + 'px'});
            // move text up/down if extends out of window
            textBottomSpace = (winBottom - opts.windowMargin) - ($text.offset().top + $text.outerHeight(true));
            var yShift = shadowShiftY;
            if (textBottomSpace < 0) {
              // shift it up
              $box.css('top', (numb($box.css('top')) + textBottomSpace) + 'px');
              yShift -= textBottomSpace;
            }
            // we ensure top space second to ensure that top of box is visible
            textTopSpace = ($text.offset().top + numb($text.css('margin-top'))) - (scrollTop + opts.windowMargin);
            if (textTopSpace < 0) {
              // shift it down
              $box.css('top', (numb($box.css('top')) - textTopSpace) + 'px');
              yShift += textTopSpace;
            }
            textTop = $text.btPosition().top + numb($text.css('margin-top'));
            textLeft = $text.btPosition().left + numb($text.css('margin-left'));
            textRight = textLeft + $text.btOuterWidth();
            textBottom = textTop + $text.outerHeight();
            textCenter = {x: textLeft + ($text.btOuterWidth()*opts.centerPointX), y: textTop + ($text.outerHeight()*opts.centerPointY)};
            points[points.length] = spikePoint = {x: textRight + opts.spikeLength, y: ((textBottom-textTop) * .5) + yShift, type: 'spike'};
            crossPoint = findIntersectY(spikePoint.x, spikePoint.y, textCenter.x, textCenter.y, textRight);
            // make sure that the crossPoint is not outside of text box boundaries
            crossPoint.y = crossPoint.y < textTop + opts.spikeGirth/2 + opts.cornerRadius ? textTop + opts.spikeGirth/2 + opts.cornerRadius : crossPoint.y;
            crossPoint.y =  crossPoint.y > (textBottom - opts.spikeGirth/2) - opts.cornerRadius ? (textBottom - opts.spikeGirth/2) - opts.cornerRadius : crossPoint.y;
            points[points.length] = {x: textRight, y: crossPoint.y + opts.spikeGirth/2, type: 'join'};
            points[points.length] = {x: textRight, y: textBottom, type: 'corner'}; // right bottom corner
            points[points.length] = {x: textLeft, y: textBottom, type: 'corner'};  // left bottom corner
            points[points.length] = {x: textLeft, y: textTop, type: 'corner'};     // left top corner
            points[points.length] = {x: textRight, y: textTop, type: 'corner'};    // right top corner
            points[points.length] = {x: textRight, y: crossPoint.y - opts.spikeGirth/2, type: 'join'};
            points[points.length] = spikePoint;
            break;
            
          // =================== BOTTOM =======================
          case 'bottom':
            // spike on top
            $text.css('margin-top', opts.spikeLength + 'px');
            $box.css({top: (top + height) - opts.overlap, left: horiz});
            // move text up/down if extends out of window
            textRightSpace = (winRight - opts.windowMargin) - ($text.offset().left + $text.btOuterWidth(true));
            var xShift = shadowShiftX;
            if (textRightSpace < 0) {
              // shift it left
              $box.css('left', (numb($box.css('left')) + textRightSpace) + 'px');
              xShift -= textRightSpace;
            }
            // we ensure left space second to ensure that left of box is visible
            textLeftSpace = ($text.offset().left + numb($text.css('margin-left')))  - (scrollLeft + opts.windowMargin);
            if (textLeftSpace < 0) {
              // shift it right
              $box.css('left', (numb($box.css('left')) - textLeftSpace) + 'px');
              xShift += textLeftSpace;
            }
            textTop = $text.btPosition().top + numb($text.css('margin-top'));
            textLeft = $text.btPosition().left + numb($text.css('margin-left'));
            textRight = textLeft + $text.btOuterWidth();
            textBottom = textTop + $text.outerHeight();
            textCenter = {x: textLeft + ($text.btOuterWidth()*opts.centerPointX), y: textTop + ($text.outerHeight()*opts.centerPointY)};
            points[points.length] = spikePoint = {x: ((textRight-textLeft) * .5) + xShift, y: shadowShiftY, type: 'spike'};
            crossPoint = findIntersectX(spikePoint.x, spikePoint.y, textCenter.x, textCenter.y, textTop);
            // make sure that the crossPoint is not outside of text box boundaries
            crossPoint.x = crossPoint.x < textLeft + opts.spikeGirth/2 + opts.cornerRadius ? textLeft + opts.spikeGirth/2 + opts.cornerRadius : crossPoint.x;
            crossPoint.x =  crossPoint.x > (textRight - opts.spikeGirth/2) - opts.cornerRadius ? (textRight - opts.spikeGirth/2) - opts.cornerRadius : crossPoint.x;
            points[points.length] = {x: crossPoint.x + opts.spikeGirth/2, y: textTop, type: 'join'};
            points[points.length] = {x: textRight, y: textTop, type: 'corner'};    // right top corner
            points[points.length] = {x: textRight, y: textBottom, type: 'corner'}; // right bottom corner
            points[points.length] = {x: textLeft, y: textBottom, type: 'corner'};  // left bottom corner
            points[points.length] = {x: textLeft, y: textTop, type: 'corner'};     // left top corner
            points[points.length] = {x: crossPoint.x - (opts.spikeGirth/2), y: textTop, type: 'join'};
            points[points.length] = spikePoint;
            break;
          
          // =================== RIGHT =======================
          case 'right':
            // spike on left
            $text.css('margin-left', (opts.spikeLength + 'px'));
            $box.css({top: vert + 'px', left: ((left + width) - opts.overlap) + 'px'});
            // move text up/down if extends out of window
            textBottomSpace = (winBottom - opts.windowMargin) - ($text.offset().top + $text.outerHeight(true));
            var yShift = shadowShiftY;
            if (textBottomSpace < 0) {
              // shift it up
              $box.css('top', (numb($box.css('top')) + textBottomSpace) + 'px');
              yShift -= textBottomSpace;
            }
            // we ensure top space second to ensure that top of box is visible
            textTopSpace = ($text.offset().top + numb($text.css('margin-top'))) - (scrollTop + opts.windowMargin);
            if (textTopSpace < 0) {
              // shift it down
              $box.css('top', (numb($box.css('top')) - textTopSpace) + 'px');
              yShift += textTopSpace;
            }
            textTop = $text.btPosition().top + numb($text.css('margin-top'));
            textLeft = $text.btPosition().left + numb($text.css('margin-left'));
            textRight = textLeft + $text.btOuterWidth();
            textBottom = textTop + $text.outerHeight();
            textCenter = {x: textLeft + ($text.btOuterWidth()*opts.centerPointX), y: textTop + ($text.outerHeight()*opts.centerPointY)};
            points[points.length] = spikePoint = {x: shadowShiftX, y: ((textBottom-textTop) * .5) + yShift, type: 'spike'};
            crossPoint = findIntersectY(spikePoint.x, spikePoint.y, textCenter.x, textCenter.y, textLeft);
            // make sure that the crossPoint is not outside of text box boundaries
            crossPoint.y = crossPoint.y < textTop + opts.spikeGirth/2 + opts.cornerRadius ? textTop + opts.spikeGirth/2 + opts.cornerRadius : crossPoint.y;
            crossPoint.y =  crossPoint.y > (textBottom - opts.spikeGirth/2) - opts.cornerRadius ? (textBottom - opts.spikeGirth/2) - opts.cornerRadius : crossPoint.y;
            points[points.length] = {x: textLeft, y: crossPoint.y - opts.spikeGirth/2, type: 'join'};
            points[points.length] = {x: textLeft, y: textTop, type: 'corner'};     // left top corner
            points[points.length] = {x: textRight, y: textTop, type: 'corner'};    // right top corner
            points[points.length] = {x: textRight, y: textBottom, type: 'corner'}; // right bottom corner
            points[points.length] = {x: textLeft, y: textBottom, type: 'corner'};  // left bottom corner
            points[points.length] = {x: textLeft, y: crossPoint.y + opts.spikeGirth/2, type: 'join'};
            points[points.length] = spikePoint;
            break;
        } // </ switch >
        
        var canvas = document.createElement('canvas');
        $(canvas).attr('width', (numb($text.btOuterWidth(true)) + opts.strokeWidth*2 + shadowMarginX)).attr('height', (numb($text.outerHeight(true)) + opts.strokeWidth*2 + shadowMarginY)).appendTo($box).css({position: 'absolute', zIndex: opts.boxzIndex});

  
        // if excanvas is set up, we need to initialize the new canvas element
        if (typeof G_vmlCanvasManager != 'undefined') {
          canvas = G_vmlCanvasManager.initElement(canvas);
        }
  
        if (opts.cornerRadius > 0) {
          // round the corners!
          var newPoints = new Array();
          var newPoint;
          for (var i=0; i<points.length; i++) {
            if (points[i].type == 'corner') {
              // create two new arc points
              // find point between this and previous (using modulo in case of ending)
              newPoint = betweenPoint(points[i], points[(i-1)%points.length], opts.cornerRadius);
              newPoint.type = 'arcStart';
              newPoints[newPoints.length] = newPoint;
              // the original corner point
              newPoints[newPoints.length] = points[i];
              // find point between this and next
              newPoint = betweenPoint(points[i], points[(i+1)%points.length], opts.cornerRadius);
              newPoint.type = 'arcEnd';
              newPoints[newPoints.length] = newPoint;
            }
            else {
              newPoints[newPoints.length] = points[i];
            }
          }
          // overwrite points with new version
          points = newPoints;
        }
        
        var ctx = canvas.getContext("2d");
        
        if (opts.shadow && opts.shadowOverlap !== true) {
          
          var shadowOverlap = numb(opts.shadowOverlap);
          
          // keep the shadow (and canvas) from overlapping the target element
          switch (position) {
            case 'top':
              if (opts.shadowOffsetX + opts.shadowBlur - shadowOverlap > 0) {
                $box.css('top', (numb($box.css('top')) - (opts.shadowOffsetX + opts.shadowBlur - shadowOverlap)));
              }
              break;
            case 'right':
              if (shadowShiftX - shadowOverlap > 0) {
                $box.css('left', (numb($box.css('left')) + shadowShiftX - shadowOverlap));
              }
              break;
            case 'bottom':
              if (shadowShiftY - shadowOverlap > 0) {
                $box.css('top', (numb($box.css('top')) + shadowShiftY - shadowOverlap));
              }
              break;
            case 'left':
              if (opts.shadowOffsetY + opts.shadowBlur - shadowOverlap > 0) {
                $box.css('left', (numb($box.css('left')) - (opts.shadowOffsetY + opts.shadowBlur - shadowOverlap)));
              }
              break;
          }
        }
  
        drawIt.apply(ctx, [points], opts.strokeWidth);
        ctx.fillStyle = opts.fill;
        if (opts.shadow) {
          ctx.shadowOffsetX = opts.shadowOffsetX;
          ctx.shadowOffsetY = opts.shadowOffsetY;
          ctx.shadowBlur = opts.shadowBlur;
          ctx.shadowColor =  opts.shadowColor;
        }
        ctx.closePath();
        ctx.fill();
        if (opts.strokeWidth > 0) {
          ctx.shadowColor = 'rgba(0, 0, 0, 0)'; //remove shadow from stroke
          ctx.lineWidth = opts.strokeWidth;
          ctx.strokeStyle = opts.strokeStyle;
          ctx.beginPath();
          drawIt.apply(ctx, [points], opts.strokeWidth);
          ctx.closePath();
          ctx.stroke();
        }
          
        // trigger preShow function
        // function receives the box element (the balloon wrapper div) as an argument
        opts.preShow.apply(this, [$box[0]]);
        
        // switch from visibility: hidden to display: none so we can run animations
        $box.css({display:'none', visibility: 'visible'});
  
        // Here's where we show the tip
        opts.showTip.apply(this, [$box[0]]);
          
        if (opts.overlay) {
          // EXPERIMENTAL AND FOR TESTING ONLY!!!!
          var overlay = $('<div class="bt-overlay"></div>').css({
              position: 'absolute',
              backgroundColor: 'blue',
              top: top,
              left: left,
              width: width,
              height: height,
              opacity: '.2'
            }).appendTo(offsetParent);
          $(this).data('overlay', overlay);
        }
        
        if ((opts.ajaxPath != null && opts.ajaxCache == false) || ajaxTimeout) {
          // if ajaxCache is not enabled or if there was a server timeout,
          // remove the content variable so it will be loaded again from server
          content = false;
        }
        
        // stick this element into the clickAnywhereToClose stack
        if (opts.clickAnywhereToClose) {
          jQuery.bt.vars.clickAnywhereStack.push(this);
          $(document).click(jQuery.bt.docClick);
        }
        
        // stick this element into the closeWhenOthersOpen stack
        if (opts.closeWhenOthersOpen) {
          jQuery.bt.vars.closeWhenOpenStack.push(this);
        }
  
        // trigger postShow function
        // function receives the box element (the balloon wrapper div) as an argument
        opts.postShow.apply(this, [$box[0]]);
  
  
      }; // </ turnOn() >
  
      this.btOff = function() {
      
        var box = $(this).data('bt-box');
  
        // trigger preHide function
        // function receives the box element (the balloon wrapper div) as an argument
        opts.preHide.apply(this, [box]);
        
        var i = this;
        
        // set up the stuff to happen AFTER the tip is hidden
        i.btCleanup = function(){
          var box = $(i).data('bt-box');
          var contentOrig = $(i).data('bt-content-orig');
          var overlay = $(i).data('bt-overlay');
          if (typeof box == 'object') {
            $(box).remove();
            $(i).removeData('bt-box');
          }
          if (typeof contentOrig == 'object') {
            var clones = $(contentOrig.original).data('bt-clones');
            $(contentOrig).data('bt-clones', arrayRemove(clones, contentOrig.clone));        
          }
          if (typeof overlay == 'object') {
            $(overlay).remove();
            $(i).removeData('bt-overlay');
          }
          
          // remove this from the stacks
          jQuery.bt.vars.clickAnywhereStack = arrayRemove(jQuery.bt.vars.clickAnywhereStack, i);
          jQuery.bt.vars.closeWhenOpenStack = arrayRemove(jQuery.bt.vars.closeWhenOpenStack, i);
          
          // remove the 'bt-active' and activeClass classes from target
          $(i).removeClass('bt-active ' + opts.activeClass);
          
          // trigger postHide function
          // no box argument since it has been removed from the DOM
          opts.postHide.apply(i);
          
        }
        
        opts.hideTip.apply(this, [box, i.btCleanup]);

      }; // </ turnOff() >
  
      var refresh = this.btRefresh = function() {
        this.btOff();
        this.btOn();
      };
  
    }); // </ this.each() >
  
  
    function drawIt(points, strokeWidth) {
      this.moveTo(points[0].x, points[0].y);
      for (i=1;i<points.length;i++) {
        if (points[i-1].type == 'arcStart') {
          // if we're creating a rounded corner
          //ctx.arc(round5(points[i].x), round5(points[i].y), points[i].startAngle, points[i].endAngle, opts.cornerRadius, false);
          this.quadraticCurveTo(round5(points[i].x, strokeWidth), round5(points[i].y, strokeWidth), round5(points[(i+1)%points.length].x, strokeWidth), round5(points[(i+1)%points.length].y, strokeWidth));
          i++;
          //ctx.moveTo(round5(points[i].x), round5(points[i].y));
        }
        else {
          this.lineTo(round5(points[i].x, strokeWidth), round5(points[i].y, strokeWidth));
        }
      }
    }; // </ drawIt() >
  
    /**
     * For odd stroke widths, round to the nearest .5 pixel to avoid antialiasing
     * http://developer.mozilla.org/en/Canvas_tutorial/Applying_styles_and_colors
     */
    function round5(num, strokeWidth) {
      var ret;
      strokeWidth = numb(strokeWidth);
      if (strokeWidth%2) {
        ret = num;
      }
      else {
        ret = Math.round(num - .5) + .5;
      }
      return ret;
    }; // </ round5() >
  
    /**
     * Ensure that a number is a number... or zero
     */
    function numb(num) {
      return parseInt(num) || 0;
    }; // </ numb() >
    
    /**
     * Remove an element from an array
     */ 
    function arrayRemove(arr, elem) {
      var x, newArr = new Array();
      for (x in arr) {
        if (arr[x] != elem) {
          newArr.push(arr[x]);
        }
      }
      return newArr;
    }; // </ arrayRemove() >
    
    /**
     * Does the current browser support canvas?
     * This is a variation of http://code.google.com/p/browser-canvas-support/
     */
    function canvasSupport() {
      var canvas_compatible = false;
      try {
        canvas_compatible = !!(document.createElement('canvas').getContext('2d')); // S60
      } catch(e) {
        canvas_compatible = !!(document.createElement('canvas').getContext); // IE
      } 
      return canvas_compatible;
    }
    
    /**
     * Does the current browser support canvas drop shadows?
     */
    function shadowSupport() {
      
      // to test for drop shadow support in the current browser, uncomment the next line
      // return true;
    
      // until a good feature-detect is found, we have to look at user agents
      try {
        var userAgent = navigator.userAgent.toLowerCase();      
        if (/webkit/.test(userAgent)) {
          // WebKit.. let's go!
          return true;
        }
        else if (/gecko|mozilla/.test(userAgent) && parseFloat(userAgent.match(/firefox\/(\d+(?:\.\d+)+)/)[1]) >= 3.1){
          // Mozilla 3.1 or higher
          return true;
        }
      }
      catch(err) {
        // if there's an error, just keep going, we'll assume that drop shadows are not supported
      }
            
      return false;
      
    } // </ shadowSupport() >
  
    /**
     * Given two points, find a point which is dist pixels from point1 on a line to point2
     */
    function betweenPoint(point1, point2, dist) {
      // figure out if we're horizontal or vertical
      var y, x;
      if (point1.x == point2.x) {
        // vertical
        y = point1.y < point2.y ? point1.y + dist : point1.y - dist;
        return {x: point1.x, y: y};
      }
      else if (point1.y == point2.y) {
        // horizontal
        x = point1.x < point2.x ? point1.x + dist : point1.x - dist;
        return {x:x, y: point1.y};
      }
    }; // </ betweenPoint() >
  
    function centerPoint(arcStart, corner, arcEnd) {
      var x = corner.x == arcStart.x ? arcEnd.x : arcStart.x;
      var y = corner.y == arcStart.y ? arcEnd.y : arcStart.y;
      var startAngle, endAngle;
      if (arcStart.x < arcEnd.x) {
        if (arcStart.y > arcEnd.y) {
          // arc is on upper left
          startAngle = (Math.PI/180)*180;
          endAngle = (Math.PI/180)*90;
        }
        else {
          // arc is on upper right
          startAngle = (Math.PI/180)*90;
          endAngle = 0;
        }
      }
      else {
        if (arcStart.y > arcEnd.y) {
          // arc is on lower left
          startAngle = (Math.PI/180)*270;
          endAngle = (Math.PI/180)*180;
        }
        else {
          // arc is on lower right
          startAngle = 0;
          endAngle = (Math.PI/180)*270;
        }
      }
      return {x: x, y: y, type: 'center', startAngle: startAngle, endAngle: endAngle};
    }; // </ centerPoint() >
  
    /**
     * Find the intersection point of two lines, each defined by two points
     * arguments are x1, y1 and x2, y2 for r1 (line 1) and r2 (line 2)
     * It's like an algebra party!!!
     */
    function findIntersect(r1x1, r1y1, r1x2, r1y2, r2x1, r2y1, r2x2, r2y2) {
  
      if (r2x1 == r2x2) {
        return findIntersectY(r1x1, r1y1, r1x2, r1y2, r2x1);
      }
      if (r2y1 == r2y2) {
        return findIntersectX(r1x1, r1y1, r1x2, r1y2, r2y1);
      }
  
      // m = (y1 - y2) / (x1 - x2)  // <-- how to find the slope
      // y = mx + b                 // the 'classic' linear equation
      // b = y - mx                 // how to find b (the y-intersect)
      // x = (y - b)/m              // how to find x
      var r1m = (r1y1 - r1y2) / (r1x1 - r1x2);
      var r1b = r1y1 - (r1m * r1x1);
      var r2m = (r2y1 - r2y2) / (r2x1 - r2x2);
      var r2b = r2y1 - (r2m * r2x1);
  
      var x = (r2b - r1b) / (r1m - r2m);
      var y = r1m * x + r1b;
  
      return {x: x, y: y};
    }; // </ findIntersect() >
  
    /**
     * Find the y intersection point of a line and given x vertical
     */
    function findIntersectY(r1x1, r1y1, r1x2, r1y2, x) {
      if (r1y1 == r1y2) {
        return {x: x, y: r1y1};
      }
      var r1m = (r1y1 - r1y2) / (r1x1 - r1x2);
      var r1b = r1y1 - (r1m * r1x1);
  
      var y = r1m * x + r1b;
  
      return {x: x, y: y};
    }; // </ findIntersectY() >
  
    /**
     * Find the x intersection point of a line and given y horizontal
     */
    function findIntersectX(r1x1, r1y1, r1x2, r1y2, y) {
      if (r1x1 == r1x2) {
        return {x: r1x1, y: y};
      }
      var r1m = (r1y1 - r1y2) / (r1x1 - r1x2);
      var r1b = r1y1 - (r1m * r1x1);
  
      // y = mx + b     // your old friend, linear equation
      // x = (y - b)/m  // linear equation solved for x
      var x = (y - r1b) / r1m;
  
      return {x: x, y: y};
  
    }; // </ findIntersectX() >
  
  }; // </ jQuery.fn.bt() >
  
  /**
   * jQuery's compat.js (used in Drupal's jQuery upgrade module, overrides the $().position() function
   *  this is a copy of that function to allow the plugin to work when compat.js is present
   *  once compat.js is fixed to not override existing functions, this function can be removed
   *  and .btPosion() can be replaced with .position() above...
   */
  jQuery.fn.btPosition = function() {
  
    function num(elem, prop) {
      return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
    };
  
    var left = 0, top = 0, results;
  
    if ( this[0] ) {
      // Get *real* offsetParent
      var offsetParent = this.offsetParent(),
  
      // Get correct offsets
      offset       = this.offset(),
      parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
  
      // Subtract element margins
      // note: when an element has margin: auto the offsetLeft and marginLeft
      // are the same in Safari causing offset.left to incorrectly be 0
      offset.top  -= num( this, 'marginTop' );
      offset.left -= num( this, 'marginLeft' );
  
      // Add offsetParent borders
      parentOffset.top  += num( offsetParent, 'borderTopWidth' );
      parentOffset.left += num( offsetParent, 'borderLeftWidth' );
  
      // Subtract the two offsets
      results = {
        top:  offset.top  - parentOffset.top,
        left: offset.left - parentOffset.left
      };
    }
  
    return results;
  }; // </ jQuery.fn.btPosition() >
  
  
  /**
  * jQuery's dimensions.js overrides the $().btOuterWidth() function
  *  this is a copy of original jQuery's outerWidth() function to 
  *  allow the plugin to work when dimensions.js is present
  */
  jQuery.fn.btOuterWidth = function(margin) {
  
      function num(elem, prop) {
          return elem[0] && parseInt(jQuery.curCSS(elem[0], prop, true), 10) || 0;
      };
  
      return this["innerWidth"]()
      + num(this, "borderLeftWidth")
      + num(this, "borderRightWidth")
      + (margin ? num(this, "marginLeft")
      + num(this, "marginRight") : 0);
  
  }; // </ jQuery.fn.btOuterWidth() >
  
  /**
   * A convenience function to run btOn() (if available)
   * for each selected item
   */
  jQuery.fn.btOn = function() {
    return this.each(function(index){
      if (jQuery.isFunction(this.btOn)) {
        this.btOn();
      }
    });
  }; // </ $().btOn() >
  
  /**
   * 
   * A convenience function to run btOff() (if available)
   * for each selected item
   */
  jQuery.fn.btOff = function() {
    return this.each(function(index){
      if (jQuery.isFunction(this.btOff)) {
        this.btOff();
      }
    });
  }; // </ $().btOff() >
  
  jQuery.bt.vars = {clickAnywhereStack: [], closeWhenOpenStack: []};
  
  /**
   * This function gets bound to the document's click event
   * It turns off all of the tips in the click-anywhere-to-close stack
   */
  jQuery.bt.docClick = function(e) {
    if (!e) {
      var e = window.event;
    };
    // if clicked element is a child of neither a tip NOR a target
    // and there are tips in the stack
    if (!$(e.target).parents().andSelf().filter('.bt-wrapper, .bt-active').length && jQuery.bt.vars.clickAnywhereStack.length) {
      // if clicked element isn't inside tip, close tips in stack
      $(jQuery.bt.vars.clickAnywhereStack).btOff();
      $(document).unbind('click', jQuery.bt.docClick);
    }
  }; // </ docClick() >
  
  /**
   * Defaults for the beauty tips
   *
   * Note this is a variable definition and not a function. So defaults can be
   * written for an entire page by simply redefining attributes like so:
   *
   *   jQuery.bt.options.width = 400;
   *
   * Be sure to use *jQuery.bt.options* and not jQuery.bt.defaults when overriding
   *
   * This would make all Beauty Tips boxes 400px wide.
   *
   * Each of these options may also be overridden during
   *
   * Can be overriden globally or at time of call.
   *
   */
  jQuery.bt.defaults = {
    trigger:         'hover',                // trigger to show/hide tip
                                             // use [on, off] to define separate on/off triggers
                                             // also use space character to allow multiple  to trigger
                                             // examples:
                                             //   ['focus', 'blur'] // focus displays, blur hides
                                             //   'dblclick'        // dblclick toggles on/off
                                             //   ['focus mouseover', 'blur mouseout'] // multiple triggers
                                             //   'now'             // shows/hides tip without event
                                             //   'none'            // use $('#selector').btOn(); and ...btOff();
                                             //   'hoverIntent'     // hover using hoverIntent plugin (settings below)
                                             // note:
                                             //   hoverIntent becomes default if available
                                             
    clickAnywhereToClose: true,              // clicking anywhere outside of the tip will close it 
    closeWhenOthersOpen: false,              // tip will be closed before another opens - stop >= 2 tips being on
                                             
    shrinkToFit:      false,                 // should short single-line content get a narrower balloon?
    width:            '200px',               // width of tooltip box
    
    padding:          '10px',                // padding for content (get more fine grained with cssStyles)
    spikeGirth:       10,                    // width of spike
    spikeLength:      15,                    // length of spike
    overlap:          0,                     // spike overlap (px) onto target (can cause problems with 'hover' trigger)
    overlay:          false,                 // display overlay on target (use CSS to style) -- BUGGY!
    killTitle:        true,                  // kill title tags to avoid double tooltips
  
    textzIndex:       9999,                  // z-index for the text
    boxzIndex:        9998,                  // z-index for the "talk" box (should always be less than textzIndex)
    wrapperzIndex:    9997,
    offsetParent:     null,                  // DOM node to append the tooltip into.
                                             // Must be positioned relative or absolute. Can be selector or object
    positions:        ['most'],              // preference of positions for tip (will use first with available space)
                                             // possible values 'top', 'bottom', 'left', 'right' as an array in order of
                                             // preference. Last value will be used if others don't have enough space.
                                             // or use 'most' to use the area with the most space
    fill:             "rgb(255, 255, 102)",  // fill color for the tooltip box, you can use any CSS-style color definition method
                                             // http://www.w3.org/TR/css3-color/#numerical - not all methods have been tested
    
    windowMargin:     10,                    // space (px) to leave between text box and browser edge
  
    strokeWidth:      1,                     // width of stroke around box, **set to 0 for no stroke**
    strokeStyle:      "#000",                // color/alpha of stroke
  
    cornerRadius:     5,                     // radius of corners (px), set to 0 for square corners
    
                      // following values are on a scale of 0 to 1 with .5 being centered
    
    centerPointX:     .5,                    // the spike extends from center of the target edge to this point
    centerPointY:     .5,                    // defined by percentage horizontal (x) and vertical (y)
      
    shadow:           false,                 // use drop shadow? (only displays in Safari and FF 3.1) - experimental
    shadowOffsetX:    2,                     // shadow offset x (px)
    shadowOffsetY:    2,                     // shadow offset y (px)
    shadowBlur:       3,                     // shadow blur (px)
    shadowColor:      "#000",                // shadow color/alpha
    shadowOverlap:   false,                  // when shadows overlap the target element it can cause problem with hovering
                                             // set this to true to overlap or set to a numeric value to define the amount of overlap
    noShadowOpts:     {strokeStyle: '#999'},  // use this to define 'fall-back' options for browsers which don't support drop shadows
    
    cssClass:         '',                    // CSS class to add to the box wrapper div (of the TIP)
    cssStyles:        {},                    // styles to add the text box
                                             //   example: {fontFamily: 'Georgia, Times, serif', fontWeight: 'bold'}
                                                 
    activeClass:      'bt-active',           // class added to TARGET element when its BeautyTip is active
  
    contentSelector:  "$(this).attr('title')", // if there is no content argument, use this selector to retrieve the title
                                             // a function which returns the content may also be passed here
  
    ajaxPath:         null,                  // if using ajax request for content, this contains url and (opt) selector
                                             // this will override content and contentSelector
                                             // examples (see jQuery load() function):
                                             //   '/demo.html'
                                             //   '/help/ajax/snip'
                                             //   '/help/existing/full div#content'
                                             
                                             // ajaxPath can also be defined as an array
                                             // in which case, the first value will be parsed as a jQuery selector
                                             // the result of which will be used as the ajaxPath
                                             // the second (optional) value is the content selector as above
                                             // examples:
                                             //    ["$(this).attr('href')", 'div#content']
                                             //    ["$(this).parents('.wrapper').find('.title').attr('href')"]
                                             //    ["$('#some-element').val()"]
                                             
    ajaxError:        '<strong>ERROR:</strong> <em>%error</em>',
                                             // error text, use "%error" to insert error from server
    ajaxLoading:     '<blink>Loading...</blink>',  // yes folks, it's the blink tag!
    ajaxData:         {},                    // key/value pairs
    ajaxType:         'GET',                 // 'GET' or 'POST'
    ajaxCache:        true,                  // cache ajax results and do not send request to same url multiple times
    ajaxOpts:         {},                    // any other ajax options - timeout, passwords, processing functions, etc...
                                             // see http://docs.jquery.com/Ajax/jQuery.ajax#options
                                      
    preBuild:         function(){},          // function to run before popup is built
    preShow:          function(box){},       // function to run before popup is displayed
    showTip:          function(box){
                        $(box).show();
                      },
    postShow:         function(box){},       // function to run after popup is built and displayed
    
    preHide:          function(box){},       // function to run before popup is removed
    hideTip:          function(box, callback) {
                        $(box).hide();
                        callback();   // you MUST call "callback" at the end of your animations
                      },
    postHide:         function(){},          // function to run after popup is removed
    
    hoverIntentOpts:  {                          // options for hoverIntent (if installed)
                        interval: 300,           // http://cherne.net/brian/resources/jquery.hoverIntent.html
                        timeout: 500
                      }
                                                 
  }; // </ jQuery.bt.defaults >
  
  jQuery.bt.options = {};

})(jQuery);

// @todo
// use larger canvas (extend to edge of page when windowMargin is active)
// add options to shift position of tip vert/horiz and position of spike tip
// create drawn (canvas) shadows
// use overlay to allow overlap with hover
// experiment with making tooltip a subelement of the target
// handle non-canvas-capable browsers elegantly
;/**
 * jQuery Ajax Rater Plugin
 *
 * This rater is based on the code Ritesh Agrawal did. Unfortunatly his CSS and the hover technique breaks in some browsers.
 * So i thought, why not use the best CSS star-rater known to man kind and throw it in the mix.
 * I have used the CSS and technique from Komodo Media since it is stable and tested on many, many browsers.
 *
 * This rater compared, has no cancel button. But i think we can live with that :)
 * To avoid conflicts i have changed the function name.
 *
 * Licensed under The MIT License
 *
 * @version     1.0
 * @since       03.01.2007
 * @author      Kjell Bublitz <m3nt0r.de@gmail.com
 * @link        http://www.m3nt0r.de/devel/raterDemo/ Demonstration and Documentation
 * @link        http://php.scripts.psu.edu/rja171/widgets/rating.php Based on Ritesh Agrawal Star Rating System
 * @link        http://komodomedia.com/blog/index.php/2007/01/20/css-star-rating-redux/ The Komodo Media CSS Rater Blogpost
 * @license     http://www.opensource.org/licenses/mit-license.php MIT
 * @package     jQuery Plugins
 * @subpackage  Rater
 */

/**
 * Usage: $('#rating').rater('your_servlet', {style:'basic', maxvalue:5, curvalue:0});
 *
 * @param url The address you want to post the result to.
 * @param options The style and value attributes
 *
 * Valid options:
 * ---------------------------------------
 *       style:       'basic', 'inline' OR 'small'
 *       maxvalue:    the maximum value / number of stars
 *       curvalue:    the initial value / selected stars
 */
jQuery.fn.rater = function(url, options, id)
{
	if(url == null) return;
	var settings = {
		url       : url, // post changes to
		maxvalue  : 5,   // max number of stars
		curvalue  : 3    // number of selected stars
	};

	if(options) { jQuery.extend(settings, options); };
	jQuery.extend(settings, {cancel: (settings.maxvalue > 1) ? true : false});

	var container = jQuery(this);
	jQuery.extend(container, { averageRating: settings.curvalue, url: settings.url });

	if(!settings.style || settings.style == null || settings.style == 'basic') {
		var raterwidth = settings.maxvalue * 25;
		var ratingparent = '<ul class="star-rating" style="width:'+raterwidth+'px">';
	}
	if(settings.style == 'small') {
		var raterwidth = settings.maxvalue * 10;
		var ratingparent = '<ul class="star-rating small-star" style="width:'+raterwidth+'px">';
	}
	if(settings.style == 'inline') {
		var raterwidth = settings.maxvalue * 10;
		var ratingparent = '<span class="inline-rating"><ul class="star-rating small-star" style="width:'+raterwidth+'px">';
	}
	container.append(ratingparent);

	// create rater
	var starWidth, starIndex, listitems = '';
	var curvalueWidth = Math.floor(100 / settings.maxvalue * settings.curvalue);
	for(var i = 0; i <= settings.maxvalue ; i++) {
		if (i == 0) {
			listitems+='<li class="current-rating" style="width:'+curvalueWidth+'%;">'+settings.curvalue+'/'+settings.maxvalue+'</li>';
		} else {
			starWidth = Math.floor(100 / settings.maxvalue * i);
			starIndex = (settings.maxvalue - i) + 2;
			listitems+='<li class="star"><a href="#'+i+'" title="'+i+'/'+settings.maxvalue +'" style="width:'+starWidth+'%;z-index:'+starIndex+'">'+i+'</a></li>';
		}
	}
	container.find('.star-rating').append(listitems); // i am using find here, because the span wrapped in the small style would break children()

	if(settings.maxvalue > 1) // add a container for the ajax result
	{
		container.append('<span class="star-rating-result"></span>');
	}
	var stars = jQuery(container).find('.star-rating').children('.star');
	stars.click(function()
	{
		if(settings.maxvalue == 1) // on / off
		{
			settings.curvalue = (settings.curvalue == 0) ? 1 : 0;
			jQuery(container).find('.star-rating').children('.current-rating').css({width:(settings.curvalue*100)+'%'});
			jQuery.post(container.url, { "rating": settings.curvalue, "id": id});
			return false;
		}
		else
		{

			settings.curvalue = stars.index(this) + 1;
			raterValue = jQuery(this).children('a')[0].href.split('#')[1];
			jQuery.post(container.url, { "rating": raterValue, "id": id }, function(response){
				container.children('.star-rating-result').html(response)
			});

			return false;
		}
		return true;
	});

	return this; // strict warning: anonymous function does not always return a value. fix?
}
/*
 *
 * Copyright (c) 2006-2009 Sam Collett (http://www.texotela.co.uk)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * Version 2.2.4
 * Demo: http://www.texotela.co.uk/code/jquery/select/
 *
 * $LastChangedDate: 2009-02-08 00:28:12 +0000 (Sun, 08 Feb 2009) $
 * $Rev: 6185 $
 *
 */
 
;
(function($) {
 
    /**
 * Adds (single/multiple) options to a select box (or series of select boxes)
 *
 * @name     addOption
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @example  $("#myselect").addOption("Value", "Text"); // add single value (will be selected)
 * @example  $("#myselect").addOption("Value 2", "Text 2", false); // add single value (won't be selected)
 * @example  $("#myselect").addOption({"foo":"bar","bar":"baz"}, false); // add multiple values, but don't select
 *
 */
    $.fn.addOption = function()
    {
        var add = function(el, v, t, sO)
        {
            var option = document.createElement("option");
            option.value = v, option.text = t;
            // get options
            var o = el.options;
            // get number of options
            var oL = o.length;
            if(!el.cache)
            {
                el.cache = {};
                // loop through existing options, adding to cache
                for(var i = 0; i < oL; i++)
                {
                    el.cache[o[i].value] = i;
                }
            }
            // add to cache if it isn't already
            if(typeof el.cache[v] == "undefined") el.cache[v] = oL;
            el.options[el.cache[v]] = option;
            if(sO)
            {
                option.selected = true;
            }
        };
	
        var a = arguments;
        if(a.length == 0) return this;
        // select option when added? default is true
        var sO = true;
        // multiple items
        var m = false;
        // ordered (array of objects {key:k, value:v})
        var order = false;
        // other variables
        var items, v, t;
        if(typeof(a[0]) == "object")
        {
            m = true;
            items = a[0];
            if(a[0].length != undefined){
                order = true;
            }
        }
        if(a.length >= 2)
        {
            if(typeof(a[1]) == "boolean") sO = a[1];
            else if(typeof(a[2]) == "boolean") sO = a[2];
            if(!m)
            {
                v = a[0];
                t = a[1];
            }
        }
        this.each(
            function()
            {
                if(this.nodeName.toLowerCase() != "select") return;
                if(m)
                {
                    if(order){
                        il = items.length;
                        for(i=0;i<il;++i){
                            add(this, items[i].key, items[i].value, sO);
                        }
                    } else {
                        for(var item in items)
                        {
                            add(this, item, items[item], sO);
                        }
                    }
                }
                else
                {
                    add(this, v, t, sO);
                }
            }
            );
        return this;
    };

    /**
 * Add options via ajax
 *
 * @name     ajaxAddOption
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @param    String url      Page to get options from (must be valid JSON)
 * @param    Object params   (optional) Any parameters to send with the request
 * @param    Boolean select  (optional) Select the added options, default true
 * @param    Function fn     (optional) Call this function with the select object as param after completion
 * @param    Array args      (optional) Array with params to pass to the function afterwards
 * @example  $("#myselect").ajaxAddOption("myoptions.php");
 * @example  $("#myselect").ajaxAddOption("myoptions.php", {"code" : "007"});
 * @example  $("#myselect").ajaxAddOption("myoptions.php", {"code" : "007"}, false, sortoptions, [{"dir": "desc"}]);
 *
 */
    $.fn.ajaxAddOption = function(url, params, select, fn, args)
    {
        if(typeof(url) != "string") return this;
        if(typeof(params) != "object") params = {};
        if(typeof(select) != "boolean") select = true;
        this.each(
            function()
            {
                var el = this;
                $.getJSON(url,
                    params,
                    function(r)
                    {
                        $(el).addOption(r, select);
                        if(typeof fn == "function")
                        {
                            if(typeof args == "object")
                            {
                                fn.apply(el, args);
                            } 
                            else
                            {
                                fn.call(el);
                            }
                        }
                    }
                    );
            }
            );
        return this;
    };

    /**
 * Removes an option (by value or index) from a select box (or series of select boxes)
 *
 * @name     removeOption
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @param    String|RegExp|Number what  Option to remove
 * @param    Boolean selectedOnly       (optional) Remove only if it has been selected (default false)   
 * @example  $("#myselect").removeOption("Value"); // remove by value
 * @example  $("#myselect").removeOption(/^val/i); // remove options with a value starting with 'val'
 * @example  $("#myselect").removeOption(/./); // remove all options
 * @example  $("#myselect").removeOption(/./, true); // remove all options that have been selected
 * @example  $("#myselect").removeOption(0); // remove by index
 * @example  $("#myselect").removeOption(["myselect_1","myselect_2"]); // values contained in passed array
 *
 */
    $.fn.removeOption = function()
    {
        var a = arguments;
        if(a.length == 0) return this;
        var ta = typeof(a[0]);
        var v, index;
        // has to be a string or regular expression (object in IE, function in Firefox)
        if(ta == "string" || ta == "object" || ta == "function" )
        {
            v = a[0];
            // if an array, remove items
            if(v.constructor == Array)
            {
                var l = v.length;
                for(var i = 0; i<l; i++)
                {
                    this.removeOption(v[i], a[1]); 
                }
                return this;
            }
        }
        else if(ta == "number") index = a[0];
        else return this;
        this.each(
            function()
            {
                if(this.nodeName.toLowerCase() != "select") return;
                // clear cache
                if(this.cache) this.cache = null;
                // does the option need to be removed?
                var remove = false;
                // get options
                var o = this.options;
                if(!!v)
                {
                    // get number of options
                    var oL = o.length;
                    for(var i=oL-1; i>=0; i--)
                    {
                        if(v.constructor == RegExp)
                        {
                            if(o[i].value.match(v))
                            {
                                remove = true;
                            }
                        }
                        else if(o[i].value == v)
                        {
                            remove = true;
                        }
                        // if the option is only to be removed if selected
                        if(remove && a[1] === true) remove = o[i].selected;
                        if(remove)
                        {
                            o[i] = null;
                        }
                        remove = false;
                    }
                }
                else
                {
                    // only remove if selected?
                    if(a[1] === true)
                    {
                        remove = o[index].selected;
                    }
                    else
                    {
                        remove = true;
                    }
                    if(remove)
                    {
                        this.remove(index);
                    }
                }
            }
            );
        return this;
    };

    /**
 * Sort options (ascending or descending) in a select box (or series of select boxes)
 *
 * @name     sortOptions
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @param    Boolean ascending   (optional) Sort ascending (true/undefined), or descending (false)
 * @example  // ascending
 * $("#myselect").sortOptions(); // or $("#myselect").sortOptions(true);
 * @example  // descending
 * $("#myselect").sortOptions(false);
 *
 */
    $.fn.sortOptions = function(ascending)
    {
        // get selected values first
        var sel = $(this).selectedValues();
        var a = typeof(ascending) == "undefined" ? true : !!ascending;
        this.each(
            function()
            {
                if(this.nodeName.toLowerCase() != "select") return;
                // get options
                var o = this.options;
                // get number of options
                var oL = o.length;
                // create an array for sorting
                var sA = [];
                // loop through options, adding to sort array
                for(var i = 0; i<oL; i++)
                {
                    sA[i] = {
                        v: o[i].value,
                        t: o[i].text
                    }
                }
                // sort items in array
                sA.sort(
                    function(o1, o2)
                    {
                        // option text is made lowercase for case insensitive sorting
                        o1t = o1.t.toLowerCase(), o2t = o2.t.toLowerCase();
                        // if options are the same, no sorting is needed
                        if(o1t == o2t) return 0;
                        if(a)
                        {
                            return o1t < o2t ? -1 : 1;
                        }
                        else
                        {
                            return o1t > o2t ? -1 : 1;
                        }
                    }
                    );
                // change the options to match the sort array
                for(var i = 0; i<oL; i++)
                {
                    o[i].text = sA[i].t;
                    o[i].value = sA[i].v;
                }
            }
            ).selectOptions(sel, true); // select values, clearing existing ones
        return this;
    };
    /**
 * Selects an option by value
 *
 * @name     selectOptions
 * @author   Mathias Bank (http://www.mathias-bank.de), original function
 * @author   Sam Collett (http://www.texotela.co.uk), addition of regular expression matching
 * @type     jQuery
 * @param    String|RegExp|Array value  Which options should be selected
 * can be a string or regular expression, or an array of strings / regular expressions
 * @param    Boolean clear  Clear existing selected options, default false
 * @example  $("#myselect").selectOptions("val1"); // with the value 'val1'
 * @example  $("#myselect").selectOptions(["val1","val2","val3"]); // with the values 'val1' 'val2' 'val3'
 * @example  $("#myselect").selectOptions(/^val/i); // with the value starting with 'val', case insensitive
 *
 */
    $.fn.selectOptions = function(value, clear)
    {
        var v = value;
        var vT = typeof(value);
        // handle arrays
        if(vT == "object" && v.constructor == Array)
        {
            var $this = this;
            $.each(v, function()
            {
                $this.selectOptions(this, clear);
            }
            );
        };
        var c = clear || false;
        // has to be a string or regular expression (object in IE, function in Firefox)
        if(vT != "string" && vT != "function" && vT != "object") return this;
        this.each(
            function()
            {
                if(this.nodeName.toLowerCase() != "select") return this;
                // get options
                var o = this.options;
                // get number of options
                var oL = o.length;
                for(var i = 0; i<oL; i++)
                {
                    if(v.constructor == RegExp)
                    {
                        if(o[i].value.match(v))
                        {
                            o[i].selected = true;
                        }
                        else if(c)
                        {
                            o[i].selected = false;
                        }
                    }
                    else
                    {
                        if(o[i].value == v)
                        {
                            o[i].selected = true;
                        }
                        else if(c)
                        {
                            o[i].selected = false;
                        }
                    }
                }
            }
            );
        return this;
    };

    /**
 * Copy options to another select
 *
 * @name     copyOptions
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @param    String to  Element to copy to
 * @param    String which  (optional) Specifies which options should be copied - 'all' or 'selected'. Default is 'selected'
 * @example  $("#myselect").copyOptions("#myselect2"); // copy selected options from 'myselect' to 'myselect2'
 * @example  $("#myselect").copyOptions("#myselect2","selected"); // same as above
 * @example  $("#myselect").copyOptions("#myselect2","all"); // copy all options from 'myselect' to 'myselect2'
 *
 */
    $.fn.copyOptions = function(to, which)
    {
        var w = which || "selected";
        if($(to).size() == 0) return this;
        this.each(
            function()
            {
                if(this.nodeName.toLowerCase() != "select") return this;
                // get options
                var o = this.options;
                // get number of options
                var oL = o.length;
                for(var i = 0; i<oL; i++)
                {
                    if(w == "all" || (w == "selected" && o[i].selected))
                    {
                        $(to).addOption(o[i].value, o[i].text);
                    }
                }
            }
            );
        return this;
    };

    /**
 * Checks if a select box has an option with the supplied value
 *
 * @name     containsOption
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     Boolean|jQuery
 * @param    String|RegExp value  Which value to check for. Can be a string or regular expression
 * @param    Function fn          (optional) Function to apply if an option with the given value is found.
 * Use this if you don't want to break the chaining
 * @example  if($("#myselect").containsOption("val1")) alert("Has an option with the value 'val1'");
 * @example  if($("#myselect").containsOption(/^val/i)) alert("Has an option with the value starting with 'val'");
 * @example  $("#myselect").containsOption("val1", copyoption).doSomethingElseWithSelect(); // calls copyoption (user defined function) for any options found, chain is continued
 *
 */
    $.fn.containsOption = function(value, fn)
    {
        var found = false;
        var v = value;
        var vT = typeof(v);
        var fT = typeof(fn);
        // has to be a string or regular expression (object in IE, function in Firefox)
        if(vT != "string" && vT != "function" && vT != "object") return fT == "function" ? this: found;
        this.each(
            function()
            {
                if(this.nodeName.toLowerCase() != "select") return this;
                // option already found
                if(found && fT != "function") return false;
                // get options
                var o = this.options;
                // get number of options
                var oL = o.length;
                for(var i = 0; i<oL; i++)
                {
                    if(v.constructor == RegExp)
                    {
                        if (o[i].value.match(v))
                        {
                            found = true;
                            if(fT == "function") fn.call(o[i], i);
                        }
                    }
                    else
                    {
                        if (o[i].value == v)
                        {
                            found = true;
                            if(fT == "function") fn.call(o[i], i);
                        }
                    }
                }
            }
            );
        return fT == "function" ? this : found;
    };

    /**
 * Returns values which have been selected
 *
 * @name     selectedValues
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     Array
 * @example  $("#myselect").selectedValues();
 *
 */
    $.fn.selectedValues = function()
    {
        var v = [];
        this.selectedOptions().each(
            function()
            {
                v[v.length] = this.value;
            }
            );
        return v;
    };

    /**
 * Returns text which has been selected
 *
 * @name     selectedTexts
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     Array
 * @example  $("#myselect").selectedTexts();
 *
 */
    $.fn.selectedTexts = function()
    {
        var t = [];
        this.selectedOptions().each(
            function()
            {
                t[t.length] = this.text;
            }
            );
        return t;
    };

    /**
 * Returns options which have been selected
 *
 * @name     selectedOptions
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @example  $("#myselect").selectedOptions();
 *
 */
    $.fn.selectedOptions = function()
    {
        return this.find("option:selected");
    };

})(jQuery);(function($) {


    $.fn.ajaxMultiFileUpload = function(options) {

        return this.each(function() {

			var opt = $.extend({},$.fn.ajaxMultiFileUpload.defaults, options);
			var fopt = {
    				image: "images/btn_add_photo.gif",
    				imageheight : 30,
    				imagewidth : 96,
    				width : 268,
    				onlyButton: false
				};
        	if (opt.fileTypes.match('jpg') && !opt.fileTypes.match('jpeg')) opt.fileTypes += ',jpeg';

			// add the form to the document
         	$(this).append('<input type="hidden" name="uploadCount" id="uploadCount" value="0" />' +
							'<div id="listOfFiles"><h2 class="numFiles"></h2></div><div class="responseMsg">Odpowiedź:</div><div id="response"><ul></ul></div>' +
							'<form action="' + opt.ajaxFile + '?type=cloth&server=' + opt.server + '&mode=' + opt.mode + '" method="post" enctype="multipart/form-data" id="myUploadForm" name="myUploadForm">' +
         					'<input type="hidden" name="sid" value="' + opt.sid + '" />' +
         					'<input type="hidden" name="filetypes" value="' + opt.fileTypes + '" /><div id="listOfInputs">' +
  							'<input size="1" type="file" id="img1" class="myUploadFile" name="file1" /></div></form>');
			if(opt.mode==1){
				opt.path = 'ubrania/'+(opt.sid%2)+'/'+opt.sid+'/';
			} else {
				p0 = ((opt.sid>>20)&0x03ff)?'d'+((opt.sid>>20)&0x03ff)+'/':'';
				p1 = ((opt.sid>>10)&0x03ff)?'d'+((opt.sid>>10)&0x03ff)+'/':'';
				opt.path = 'uploads/clothes/c'+(opt.sid%2)+'/'+p0+p1+opt.sid+'/';
			}	
			$(this).bind('addThumbEx', function(e, val, selected){addThumb(val, selected);});
			// delete previously uploaded file
			$("a.remove").live('click', function(){

				var _delete = this.id;
				var _this = $(this);

			//	UNCOMMENT THIS FUNCTION WHEN NOT BLOCKING FILES FROM STAYING ON SERVER
				$.get(opt.ajaxFile +"?type=cloth&server=" + opt.server + "&delete=" + _delete + "&sid=" + opt.sid + "&mode=" + opt.mode, function(returned){
					if(returned!="OK") return;
					// remove the first input.file also.  another will be added by addInput()
					deleteFileInput($("#listOfInputs input:file.myUploadFile:eq(0)"));
					_this.parent().remove();
					addInput(false);
 				});
 			});

			/**
			 *
			 * @access public
			 * @return void
			 **/
			function deleteFileInput(fileInput){
				$(fileInput).parent().prev().remove(); 				// remove the input
				$(fileInput).parent().remove(); 				// remove the input

			}

        	// update the file counter
			function updateCount(mode) {
				var cnt = $(".nameOfFile").size();
				$("#uploadCount").val(cnt);
				$("h2.numFiles").text( "dodanych zdjęć: " + cnt);
				if(cnt||mode)
				{
					fopt.image = "images/btn_add_photo_next.gif";
					$('#listOfFiles').show();
				}
				else
				{
					fopt.image = "images/btn_add_photo.gif";
					$('#listOfFiles').hide();
				}
			}

			// update the input to the form after submit
			function addInput(mode) {
				updateCount(mode);
				// add another input.file to the page and initialize the inputfile plugin
				$("#listOfInputs").prepend('<input size="1" type="file" class="myUploadFile" name="file" id="img" />');
				$("#listOfInputs input:file.myUploadFile:eq(0)").filestyle(fopt);
			}

			function addThumb(_img_name, selected)
			{
				_newFile = $('<div class="nameOfFile"></div>');

				// add thumb image
				//compute path
				img_ = new Image();
				_isrc = opt.imgPfx + opt.path + 'th_' + _img_name + (opt.mode==1?'/temp':'') + '.jpg';
				$(img_).appendTo(_newFile).attr({ src:_isrc, title:_img_name });

                _newFile.append('<a href="#" class="remove" id="'+_img_name+'">Usuń zdjęcie</a>');
                _newFile.append('<br /><input type="radio" name="set_avatar" value="'+_img_name+'" '+selected+'> <span style="font-size: 15px;">Ustaw jako zdjęcie główne</span>');
				// add to dom
				$("#listOfFiles").append(_newFile);

				// update file counter
		 		updateCount(false);
			}

			// when form input changes
			//$("input.myUploadFile").livequery('change', function(){
			$("#listOfInputs input:file.myUploadFile").live('change', function(){

				if(this.value) {
					// check file extension for approved file types
					if (opt.fileTypes.match(this.value.toLowerCase().substr(this.value.toLowerCase().lastIndexOf('.')+1))) {
						var f = $('form#myUploadForm');
						f.trigger('submit');	// submit the form
						deleteFileInput(this);
						//$(this).remove(); 				// remove the input
						addInput(true);										// add new input
					}
					else {
						alert('Typ ' + this.value.substr(this.value.lastIndexOf('.')+1) + ' jest niedozwolony');
						return false;
					}
				}
				else alert("Brak zdjęć do załadowania.");
			});

			var event = {

				frame : function() {
					// build iframe to receive form data, remove previous iFrame first
					$("iframe#myFrame").remove();
					$("body").append("<div><iframe src='about:blank' id='myFrame' name='myFrame'></iframe></div>");
					// onload iFrame, call loaded function
					$("iframe#myFrame").load(function(){
							event.loaded(this);
					});
					// return iFrame id for form target
					return 'myFrame';
				},

				submit : function(_form) {
					// onsubmit, reassign form target to iframe and show ajax loader
					_form.setAttribute('target', event.frame());
					$('#loader').show();
				},

				loaded : function(id) {
					// determine platform syntax
					if (id.contentDocument)
						var d = id.contentDocument;
					else if (id.contentWindow)
						var d = id.contentWindow.document;
					else
						var d = window.frames[id].document;

					// trim name of file returned to iFrame
					
					var _img_name = d.body.innerHTML.replace(/^\s+|\s+$/g, '');
					if(_img_name == '') return;
					// hide ajax loader
					$('#loader').hide();

					// check if php mime file type is approved
					if (_img_name.match('niedozwolony')) {
						$('#response ul').append(_img_name);
						return false;
					}
					else if(_img_name.match('Minimalny')) {
						$('#valErr').html(_img_name).show();
						jQuery(window).scrollTop(0);
                        return false;
					}
					else if(_img_name.match(/^ERR/)){
						$('#valErr').html(_img_name.substr(3)).show();
						jQuery(window).scrollTop(0);
						return false;
					}
					else {
						// build file thumb display
						
						addThumb(_img_name);
                        $('#valErr').hide().empty();
		 			}
				}
			}
			// submit form to event variable
			$('form#myUploadForm').submit(function(ev){
					ev.stopImmediatePropagation();
					return event.submit(this);
			});

			// initialize the inputfile plugin for input.file
			$("input:file.myUploadFile").filestyle(fopt);

			// update the file counter
			updateCount(false);

			// add ajax loader
			$('#listOfInputs').append("<div id='loader'><img src='images/sending-bar.gif' /><div>");
      		$('#loader').hide();

        });
	};

    // plugin defaults
    $.fn.ajaxMultiFileUpload.defaults = {
        ajaxFile: "ajax-upload.html",
        fileTypes: "jpg",
        sid: 0,
		mode: 1,
		imgPfx: 'http://img.szafa.pl/'
    };

})(jQuery);
/*##############################################################################
#    ____________________________________________________________________
#   /                                                                    \
#  |               ____  __      ___          _____  /     ___    ___     |
#  |     ____       /  \/  \  ' /   \      / /      /__   /   \  /   \    |
#  |    / _  \     /   /   / / /    /  ___/  \__   /     /____/ /    /    |
#  |   / |_  /    /   /   / / /    / /   /      \ /     /      /____/     |
#  |   \____/    /   /    \/_/    /  \__/  _____/ \__/  \___/ /           |
#  |                                                         /            |
#  |                                                                      |
#  |   Copyright (c) 2007                             MindStep SCOP SARL  |
#  |   Herve Masson                                                       |
#  |                                                                      |
#  |      www.mindstep.com                              www.mjslib.com    |
#  |   info-oss@mindstep.com                           mjslib@mjslib.com  |
#   \____________________________________________________________________/
#
#  Version: 1.0.0
#
#  (Svn version: $Id: jquery.autoimage.js 3437 2007-11-07 05:14:14Z herve $)
#
#----------[This product is distributed under a BSD license]-----------------
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#
#     1. Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#
#     2. Redistributions in binary form must reproduce the above copyright
#        notice, this list of conditions and the following disclaimer in
#        the documentation and/or other materials provided with the
#        distribution.
#
#  THIS SOFTWARE IS PROVIDED BY THE MINDSTEP CORP PROJECT ``AS IS'' AND
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
#  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MINDSTEP CORP OR CONTRIBUTORS
#  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
#  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
#  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
#  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
#  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
#  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#  The views and conclusions contained in the software and documentation
#  are those of the authors and should not be interpreted as representing
#  official policies, either expressed or implied, of MindStep Corp.
#
################################################################################
#
#	This is a jQuery [jquery.com] plugin that implements image animations
#
#	@author: Herve Masson
#	@version: 1.0 (8/5/2007)
#	@requires jQuery v1.1.2 or later
#
#	(Partly based on the legacy mjslib.org framework)
#
#	Dependencies: you need to load jquery.printf.js before this plugin
#
##############################################################################*/

/*
**	$('#image').autoimage({ options })
**
**	Options:
**
**	mouseover:
**		When true, animation progresses when the mouse is placed over the image.
**		Otherwise, animation runs contunously over time.
**
**	href:
**		specifies a link reference that will be associated with the image. When the
**		image is clicked, this link is handled the same way we set 'href'
**		to a <a> tag.
**
**	images:
**		this gives a list of secundary images to be displayed. For a mouseover
**		image, you only need one. For an animated image, you can use as many
**		as you want.
**
**	circular:
**		enable (when true) circular animation
**
**
*/

/*
**	                 =================================
**	                 >> Some Implementation details <<
**	                 =================================
**
**
**	A full animation cycle is represented by a 'pos' float value between 0 and 1:
**	=============================================================================
**
**
**	                        +--- current position
**	                        |
**	    0                   v                        1 <-- position value
**	    |---------=====|----x----=====|---------=====|
**	    |              |    ^         |              |
**	     \_ image1      \_ image2      \_ image3      \_ image4
**	       (slide1)       (slide2)       (slide3)       (slide4)
**
**
**	"-----"		the image is shown stable during this period of time
**	"====="		represents the smooth transition between images (crossfade)
**
**
**	In circular mode (loop=="cycle"):
**	=================================
**
**	The schema takes an extra slide so that the first image can follow
**	the last one.
**
**	                        +--- current position
**	                        |
**	    0                   v                                       1
**	    |---------=====|----x----=====|---------=====|---------=====|---------=====|...
**	    |              |    ^         |              |              |
**	    |    image1    |   image2     |   image3     |   image4     |     image1
**	    |   (slide1)   |  (slide2)    |  (slide3)    |  (slide4)    |    (slide1)
**
**
**	The amount of time spent in both stable and fade period is set via
**	the 'fade' parameter. It sets, in percentage, how long the fade
**	period lasts:
**
**	 - 100% means maximum fading (fadin occurs all along the slide period)
**	 - 0% means no fading
**	 - with 50%, stable and crossfading duration are equal
**
**
**	Internal representation:
**	========================
**
**	The whole sequence is converted into a list of regions. Each region is
**	defined by:
**
**	 - a length (a value in the 0...1 position domain)
**	 - an index representing the source image
**	 - an index representing the target image
**	 - a boolean that tells if this is a crossfade transition or not
**
**	For example, a non-cyclic animation made of 3 images with a fade parameter
**	set as 50% will be converted in 4 regions:
**
**	- region 1: source=0, target=undefined, length=.25, fade=false
**	- region 2: source=0, target=1, length=.25, fade=true
**	- region 3: source=1, target=undefined, length=.25, fade=false
**	- region 4: source=1, target=2, length=.25, fade=true
**
**	    0             .25              .5             .75             1 <-- position
**	    |---------------===============|---------------===============|
**	    |    region1        region2    |    region3        region4    |
**	    |                              |                              |
**	    |                              |                              |
**	     \_ image1                      \_ image2                      \_ image3
**	       (slide1)                       (slide2)                       (slide3)
**
**
**	Note: I've done this representation so that we can specify arbitrary
**	transition durations in the future (for now, all slides have the same
**	region pattern). This will come in future revisions.
**
**
**	Looping
**	=======
**
**	By default, the image animation stops when it reaches a boundary (first or
**	last images). You can change that by giving a 'loop' parameter, which can
**	take those values:
**
**	  'none'     no looping (default)
**	  'cycle'    jump to the first image when we reach the last
**	  'bounce'   change direction when we reach the first or the last image
**
*/


(function($) {

	var TIMERINTERVAL=50;

	var LOOPMODES=
	{
		cycle:	{ cycle:true },
		bounce:	{ bounce: true }
	};

	var ISIE=jQuery.browser.msie;

	$.fn.extend(
		{
			autoimage:function(opts)
				{ return this.each(function() { return $.autoimage(this,opts); });			},

			aiButton:function(opts)
				{ return this.each(function() { return $.aiButton(this,opts); });			},

			aiApplyMarkupExtensions:function()
				{ return this.each(function() { return $.aiApplyMarkupExtensions(this); });	}
		}
	);

	$.autoimage=function(image,opts)
	{
		if(opts==undefined)
		{
			errorf("options are missing in autoimage()");
			return;
		}
		if(image.aimInfo!=undefined)
		{
			errorf("image is already assigned on element ID=%s",image.id);
			return;
		}

		var srclist=opts.images;

		/*
		** Creates a container for all images (they'll be shown one by one)
		** Note: to position images within the container, the
		** container needs to have a relative positioning (don't ask me why)
		*/

		$(image).wrap("<div></div>");
		var imcontainer=image.parentNode;
		imcontainer.style.position="relative";
		// Resizes the container to fit the image exactly
		resize(imcontainer,image.offsetWidth,image.offsetHeight);

		/*
		** Now, creates alternate image(s) and move them all in absolute positions
		** at offset 0:0 so that they all fit in the same screen space
		*/

		var imlist=[image];
		if(srclist!=undefined)
		{
			for(var i=1;i<=srclist.length;i++)
			{
				var im=document.createElement('img');
				im.src=srclist[i-1];
				imcontainer.appendChild(im);
				imlist[i]=im;
			}
		}

		for(var i=0;i<imlist.length;i++)
		{
			var im=imlist[i];
			im.style.position="absolute";
			im.style.top="0px";
			im.style.left="0px";
			im.border=0;
			if(i>0)
			{
				// Only keep the primary image visible for now
				$(im).hide;
			}
		}


		/*
		** Now deals with the href option
		*/

		if(opts.href)
		{
			$(imcontainer).wrap("<a></a>");
			var anchor=imcontainer.parentNode;
			anchor.href=opts.href;
		}

		if(imlist.length==1)
		{
			// No image animation, just a link
			return;
		}

		/*
		**	Parses options; build the AutoIMage information block,
		**	and attach it to the container
		*/

		var aim=imcontainer.aimInfo=image.aimInfo=
			{
				id:			image.id,
				images:		imlist,
				count:		imlist.length,
				fade:		opts.fade,
				speed:		opts.speed,
				bwspeed:	opts.bwspeed,
				fwspeed:	opts.fwspeed,
				mouseover:	opts.mouseover
			};

		var mode=opts.loop,val;
		if(mode!=undefined)
		{
			if((val=LOOPMODES[mode])==undefined)
			{
				errorf("unknown loop mode '%s'",mode);
			}
			else
			{
				aim.bounce=val.bounce;
				aim.cycle=val.cycle;
			}
		}

		// Computes animation speed values
		if(aim.speed==undefined)
		{
			aim.speed=$.autoimage.defaults.speed;
		}
		if(aim.fwspeed==undefined)
		{
			aim.fwspeed=aim.speed;
		}
		if(aim.bwspeed==undefined)
		{
			aim.bwspeed=aim.fwspeed;
		}
		if(aim.fwspeed>0)
		{
			aim.incfactor=1/aim.fwspeed;
		}

		if(aim.fade==undefined)
		{
			aim.fade=$.autoimage.defaults.fade;
		}
		if(aim.fade===true)
		{
			aim.fade=100;
		}

		/*
		**	Build the region map
		*/

		var nslices=(aim.cycle)?aim.count:aim.count-1;
		var regsz=1/nslices;
		var reglist=[],regidx=0

		for(var i=0;i<nslices;i++)
		{
			var next=(i+1)%aim.count;
			if(aim.fade>=100)
			{
				// Full fading mode (no stable image)
				reglist[regidx++]={ source:i, target:next, length: regsz, fade:true };
			}
			else if(aim.fade<=0)
			{
				// Non fading mode
				reglist[regidx++]={ source:i, length: regsz, fade:false };
			}
			else
			{
				var fadesz=(aim.fade*regsz)/100;
				var stsz=regsz-fadesz;
				reglist[regidx++]={ source:i, length: stsz, fade:false };
				reglist[regidx++]={ source:i, target: next, length: fadesz, fade:true };
			}
		}

		// Inserts an artificial region for the non-circular mode (last image in stable mode)
		if(!aim.cycle)
		{
			reglist[regidx++]={ source:(aim.count-1), length: 0, fade:false };
		}

		aim.regions=reglist;
		aim.regcount=reglist.length;

		/*
		**	Hook necessary event handlers
		*/

		if(opts.mouseover)
		{
			//	We want the image animation to run when the mouse is over the image
			$(imcontainer).hover(
				function(){return onMouseEnter(aim)},
				function(){return onMouseLeave(aim)}
			);
		}
		else
		{
			//	Time controls the animation
			startTimeAnim(aim);
		}

		// Starts at position 0

		setPosition(aim,0);
	}

	$.aiButton=function(image,opts)
	{
		if(opts==undefined)
		{
			errorf("options are missing in aiButton()");
			return;
		}
		if(opts.oversrc!=undefined)
		{
			opts.images=[opts.oversrc];
		}
		opts.mouseover=true;
		if(opts.fade)
		{
			opts.fwspeed=$.autoimage.defaults.buttons.fwspeed;
			opts.bwspeed=$.autoimage.defaults.buttons.bwspeed;
		}
		else
		{
			opts.speed=0;
		}
		return $.autoimage(image,opts);
	}


	/*
	**	Apply autoimage markup extensions
	**	=================================
	**
	**	Because I find writing javascript hooks overkilling for small features
	**	such as overstate images, I added this possibility to extend the HTML
	**	attributes of the image element.
	**
	**	If you want to create an overstate button with fading effect between
	**	the two state images, you would write this in your HTML:
	**
	**		<img src=image1 oversrc=image2 href="javascript:bingo()" fade="true">
	**		                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	**	This markup extensions recognize the following non-conventional attributes:
	**
	**	- href: just set it as you would do with <a>
	**	- oversrc: set an overstate image
	**	- fade: set the fade value (ex: "yes","no","true","false",50,...)
	**
	**	Note: the HTML extensions are enabled by default.
	**
	*/

	function applyImageMarkup(image)
	{
		var opts={},href,oversrc,fade,doit=false;

		if(href=$(image).attr("href"))
		{
			opts.href=href;
			doit=true;
		}
		if(oversrc=$(image).attr("oversrc"))
		{
			opts.oversrc=oversrc;
			doit=true;
			if(fade=$(image).attr("fade"))
			{
				opts.fade=parseFade(fade);
			}
		}
		if(doit)
		{
			$(image).aiButton(opts);
		}
	}

	$.aiApplyMarkupExtensions=function(from)
	{
		from=from||document.body;

		$("img").each(function()
			{
				applyImageMarkup(this);
			});
	}

	/*
	**	              ========================================
	**	              >> Private code - do not use directly <<
	**	              ========================================
	*/


	/*
	**	Progress the animation
	**	======================
	**
	**	Change the animation position backward or forward, according to
	**	the current increment factor value. Stops the timer when we
	**	reached an end.
	**
	*/

	function onTimer(aim)
	{
		var now=curtime();

		if(aim.hoverlast==undefined)
		{
			aim.hoverlast=now;
		}

		var delta=now-aim.hoverlast;
		var inc=aim.incfactor*delta;
		var newpos=aim.pos+inc;

		if(!aim.cycle)
		{
			if(aim.bounce)
			{
				if(newpos>=1)
				{
					newpos=1;
					aim.incfactor=-1/aim.bwspeed;
				}
				else if(newpos<=0)
				{
					newpos=0;
					aim.incfactor=1/aim.fwspeed;
				}
			}
			else
			{
				// Clip the value in non circular mode
				newpos=newpos>1?1:newpos;
				newpos=newpos<0?0:newpos;
			}
		}

		setPosition(aim,newpos);
		aim.hoverlast=now;

		if(aim.incfactor<0 && newpos<=0)
		{
			// Backward animation finished -> we no longer need the timer
			stopHoverTimer(aim);
		}
	}


	/*
	**	Runs the animation continously
	**	==============================
	**
	*/

	function startTimeAnim(aim)
	{
		aim.timer=setInterval(function(){onTimer(aim);},TIMERINTERVAL);
	}

	/*
	**	Runs the animation on mouseover conditions:
	**	===========================================
	**
	**	In circular mode, the animation stops when the mouse leave the area,
	**	and restarts on next mouseenter at the same position.
	**
	**	In non circular mode, the animation goes backward when the mouse leave
	**	the area, until it reaches the position 0.
	**
	*/

	function stopHoverTimer(aim)
	{
		clearInterval(aim.timer);
		aim.timer=undefined;
		aim.hoverlast=undefined;
	}

	function onMouseEnter(aim)
	{
		if(aim.fwspeed<=0)
		{
			// speed=0 means instantly
			stopHoverTimer(aim);
			setPosition(aim,1);
			return;
		}
		aim.incfactor=1/aim.fwspeed;
		if(aim.timer==undefined)
		{
			aim.timer=setInterval(function(){onTimer(aim)},TIMERINTERVAL);
		}
	}

	function onMouseLeave(aim)
	{
		if(aim.bwspeed<=0)
		{
			// speed=0 means instantly
			stopHoverTimer(aim);
			setPosition(aim,0);
			return;
		}
		aim.incfactor=-1/aim.bwspeed;
		if(aim.cycle)
		{
			// circular mode: we stop where we are
			stopHoverTimer(aim);
		}
	}


	/*
	**	Set the animation position, and update image(s) accordingly
	**	===========================================================
	**
	**	This is the heart of this module. It select an arbitrary position
	**	within the animation, from 0 (start) to 1 (end).
	**
	*/

	function setPosition(aim,pos)
	{
		// Slide "size" (how much we spend in one frame)
		var slsize=1/aim.count;

		// Current image transparency
		var transp=0;

		// Current and next image indexes
		var curim;

		// Keep for later
		aim.pos=pos;

		// Sanitize the 'pos' value
		if(aim.cycle)
		{
			// In circular mode, we do modulo
			if(pos<0)
			{
				pos=pos-int(pos)+1;
			}
			if(pos>=1)
			{
				pos=pos-int(pos);
			}
		}
		else
		{
			// In non-circular mode, we do clipping (and the value 1 is okay)
			pos=pos<0?0:pos;
			pos=pos>1?1:pos;
		}

		// See if something changed since last time
		if(pos==aim.sanepos)
		{
			// We are already there
			return;
		}

		// Saves the sanitized value
		aim.sanepos=pos;

		// Parses the region list to see where we are
		var reg,regpos=pos;
		for(var i=0;i<aim.regcount;i++)
		{
			reg=aim.regions[i];
			if(reg.length>regpos)
			{
				break;
			}
			regpos-=reg.length;
		}

		if(!reg.fade)
		{
			// No crossfading here -> show the current image and hide others
			for(var i=0;i<aim.count;i++)
			{
				if(i==reg.source)
				{
					showOpaqueImage(aim.images[i]);
				}
				else
				{
					hideImage(aim.images[i]);
				}
			}
			return;
		}

		/*
		**	This is where it gets a little trickier - cross-fading
		**
		** See where we are in the image transition (0: source image, 1: dest image)
		** (This gives the opacity factor, also between 0 and 1)
		*/

		var opac=(regpos/reg.length);
		for(var i=0;i<aim.count;i++)
		{
			var im=aim.images[i];
			if(i==reg.target)
			{
				// Makes the target image the foreground image
				im.style.zIndex=1;
				setOpacity(im,opac);
				showImage(im);
			}
			else if(i==reg.source)
			{
				// Makes the source image the background image
				im.style.zIndex=0;
				showOpaqueImage(im);
			}
			else
			{
				// We don't need this one for now
				hideImage(im);
			}
		}
	}

	/*
	**	Misc utilities
	*/

	function showImage(im)			{ im.style.visibility="visible";	}
	function showOpaqueImage(im)	{ setOpacity(im,1); showImage(im);	}
	function hideImage(im)			{ im.style.visibility="hidden";		}
	function int(val)				{ return Math.floor(val);			}
	function curtime()				{ return (new Date()).getTime();	}

	if($.verrorf)
	{
		function errorf()	{ $.verrorf(arguments);	}
		function logf()		{ $.vlogf(arguments);	}
	}
	else
	{
		function errorf()	{ }
		function logf()		{ }
	}

	function setOpacity(elem,opac)
	{
		if(opac>=1 && !elem.aimHasOpac)
		{
			// Don't apply opacity filter when we never use a value != 1 before
			// (I am not sure if that worth it, but some browser might like it)
			return;
		}
		if(ISIE)
		{
			elem.style.filter="alpha(opacity=" + opac + ")";
		}
		else
		{
			elem.style.opacity=opac;
		}
		elem.aimHasOpac=true;
	}

	function resize(el,dx,dy)
	{
		if(dx != undefined)
		{
			el.style.width=dx+"px";
		}
		if(dy != undefined)
		{
			el.style.height=dy+"px";
		}
	}

	function parseFade(prm)
	{
		if(prm.constructor!=String)
		{
			return prm;
		}
		prm=prm.toLowerCase();
		// Parses the string value
		if(prm=="true" || prm=="yes")
		{
			return true;
		}
		if(prm=="false" || prm=="no")
		{
			return false;
		}
		var ival=parseInt(prm);
		if(isNaN(prm))
		{
			errorf("'%s' is not a legal value for 'fade' parameter",prm);
			return undefined;
		}
		return ival;
	}



$.autoimage.defaults=
{
	speed:			1000,		// default speed for image animation
	fade:			0,			// default fading factor, in percent

	// Defaults for aiButton()
	buttons:
		{
			fwspeed:	100,	// speed for the normal->over transition
			bwspeed:	300		// speed for the over->normal transition
		}
};

})(jQuery);


$(function()
{
	jQuery.aiApplyMarkupExtensions();
});

/*
 * Style File - jQuery plugin for styling file input elements
 *
 * Copyright (c) 2007-2008 Mika Tuupola
 *
 * Licensed under the MIT license:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Based on work by Shaun Inman
 *   http://www.shauninman.com/archive/2007/09/10/styling_file_inputs_with_css_and_the_dom
 *
 * Revision: $Id: jquery.filestyle.js 303 2008-01-30 13:53:24Z tuupola $
 *
 */

(function($) {

    $.fn.filestyle = function(options) {

        /* TODO: This should not override CSS. */
        var settings = {
            width : 250
        };

        if(options) {
            $.extend(settings, options);
        }

        return this.each(function() {

            var self = this;
            var wrapper = $("<div>")
                            .css({
                                "width": settings.imagewidth + "px",
                                "height": settings.imageheight + "px",
                                "background": "url(" + settings.image + ") 0 0 no-repeat",
                                "background-position": "right",
                                "display": "inline",
                                "position": "absolute",
                                "overflow": "hidden"
                            });

            var filename = $('<input class="file">')
                             .addClass($(self).attr("class"))
                             .css({
                                 "display": (settings.onlyButton?"none":"inline"),
                                 "width": settings.width + "px"
                             });

            $(self).before(filename);
            $(self).wrap(wrapper);

            $(self).css({
                        "position": "absolute",
                        "height": settings.imageheight + "px",
                        "display": "inline",
                        "cursor": "pointer",
                        "opacity": "0.0",
                        "margin" : "0",
                        "right" : "0"
                    });
/*
            if ($.browser.mozilla) {
                if (/Win/.test(navigator.platform)) {
                    $(self).css("margin-left", "-142px");
                } else {
                    $(self).css("margin-left", "-168px");
                };
            } else {
                $(self).css("margin-left", settings.imagewidth - settings.width + "px");
            };
*/
            $(self).bind("change", function() {
                filename.val($(self).val());
            });

        });


    };

})(jQuery);
/*
 * jQuery Cycle Plugin for light-weight slideshows
 * Examples and documentation at: http://malsup.com/jquery/cycle/
 * Copyright (c) 2007-2008 M. Alsup
 * Version: 2.28 (06-OCT-2008)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 * Requires: jQuery v1.2.3 or later
 *
 * Based on the work of:
 *  1) Matt Oakes (http://portfolio.gizone.co.uk/applications/slideshow/)
 *  2) Torsten Baldes (http://medienfreunde.com/lab/innerfade/)
 *  3) Benjamin Sterling (http://www.benjaminsterling.com/experiments/jqShuffle/)
 */
;(function($) {

var ver = '2.28';
var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent);

function log() {
    if (window.console && window.console.log)
        window.console.log('[cycle] ' + Array.prototype.join.call(arguments,''));
};

$.fn.cycle = function(options) {
	var opt2 = arguments[1];
    return this.each(function() {
        if (options === undefined || options === null)
            options = {};
        if (options.constructor == String) {
            switch(options) {
            case 'stop':
                if (this.cycleTimeout) clearTimeout(this.cycleTimeout);
                this.cycleTimeout = 0;
                $(this).data('cycle.opts', '');
                return;
            case 'pause':
                this.cyclePause = 1;
                return;
            case 'resume':
				this.cyclePause = 0;
				if (opt2 === true) { // resume now!
		            options = $(this).data('cycle.opts');
		            if (!options) {
		                log('options not found, can not resume');
		                return;
		            }
					if (this.cycleTimeout) {
						clearTimeout(this.cycleTimeout);
						this.cycleTimeout = 0;
					}            
					go(options.elements, options, 1, 1);
				}
                return;
            default:
                options = { fx: options };
            };
        }
        else if (options.constructor == Number) {
            // go to the requested slide
            var num = options;
            options = $(this).data('cycle.opts');
            if (!options) {
                log('options not found, can not advance slide');
                return;
            }
            if (num < 0 || num >= options.elements.length) {
                log('invalid slide index: ' + num);
                return;
            }
            options.nextSlide = num;
            if (this.cycleTimeout) {
                clearTimeout(this.cycleTimeout);
                this.cycleTimeout = 0;
            }            
            go(options.elements, options, 1, num >= options.currSlide);
            return;
        }

        // stop existing slideshow for this container (if there is one)
        if (this.cycleTimeout) clearTimeout(this.cycleTimeout);
        this.cycleTimeout = 0;
        this.cyclePause = 0;
        
        var $cont = $(this);
        var $slides = options.slideExpr ? $(options.slideExpr, this) : $cont.children();
        var els = $slides.get();
        if (els.length < 2) {
            log('terminating; too few slides: ' + els.length);
            return; // don't bother
        }

        // support metadata plugin (v1.0 and v2.0)
        var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {});
        if (opts.autostop) 
            opts.countdown = opts.autostopCount || els.length;

        $cont.data('cycle.opts', opts);
        opts.container = this;

        opts.elements = els;
        opts.before = opts.before ? [opts.before] : [];
        opts.after = opts.after ? [opts.after] : [];
        opts.after.unshift(function(){ opts.busy=0; });
        if (opts.continuous)
            opts.after.push(function() { go(els,opts,0,!opts.rev); });
            
        // clearType corrections
        if (ie6 && opts.cleartype && !opts.cleartypeNoBg)
            clearTypeFix($slides);

        // allow shorthand overrides of width, height and timeout
        var cls = this.className;
        opts.width = parseInt((cls.match(/w:(\d+)/)||[])[1]) || opts.width;
        opts.height = parseInt((cls.match(/h:(\d+)/)||[])[1]) || opts.height;
        opts.timeout = parseInt((cls.match(/t:(\d+)/)||[])[1]) || opts.timeout;

        if ($cont.css('position') == 'static') 
            $cont.css('position', 'relative');
        if (opts.width) 
            $cont.width(opts.width);
        if (opts.height && opts.height != 'auto') 
            $cont.height(opts.height);

		if (opts.startingSlide) opts.startingSlide = parseInt(opts.startingSlide);	
			
        if (opts.random) {
            opts.randomMap = [];
            for (var i = 0; i < els.length; i++) 
                opts.randomMap.push(i);
            opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
            opts.randomIndex = 0;
            opts.startingSlide = opts.randomMap[0];
        }
        else if (opts.startingSlide >= els.length)
            opts.startingSlide = 0; // catch bogus input
        var first = opts.startingSlide || 0;
        $slides.css({position: 'absolute', top:0, left:0}).hide().each(function(i) { 
            var z = first ? i >= first ? els.length - (i-first) : first-i : els.length-i;
            $(this).css('z-index', z) 
        });
        
        $(els[first]).css('opacity',1).show(); // opacity bit needed to handle reinit case
        if ($.browser.msie) els[first].style.removeAttribute('filter');

        if (opts.fit && opts.width) 
            $slides.width(opts.width);
        if (opts.fit && opts.height && opts.height != 'auto') 
            $slides.height(opts.height);
        if (opts.pause) 
            $cont.hover(function(){this.cyclePause=1;},function(){this.cyclePause=0;});

        // run transition init fn
        var init = $.fn.cycle.transitions[opts.fx];
        if ($.isFunction(init))
            init($cont, $slides, opts);
        else if (opts.fx != 'custom')
            log('unknown transition: ' + opts.fx);
        
        $slides.each(function() {
            var $el = $(this);
            this.cycleH = (opts.fit && opts.height) ? opts.height : $el.height();
            this.cycleW = (opts.fit && opts.width) ? opts.width : $el.width();
        });

        opts.cssBefore = opts.cssBefore || {};
        opts.animIn = opts.animIn || {};
        opts.animOut = opts.animOut || {};

        $slides.not(':eq('+first+')').css(opts.cssBefore);
        if (opts.cssFirst)
            $($slides[first]).css(opts.cssFirst);

        if (opts.timeout) {
			opts.timeout = parseInt(opts.timeout);
            // ensure that timeout and speed settings are sane
            if (opts.speed.constructor == String)
                opts.speed = $.fx.speeds[opts.speed] || parseInt(opts.speed);
            if (!opts.sync)
                opts.speed = opts.speed / 2;
            while((opts.timeout - opts.speed) < 250)
                opts.timeout += opts.speed;
        }
        if (opts.easing) 
            opts.easeIn = opts.easeOut = opts.easing;
        if (!opts.speedIn) 
            opts.speedIn = opts.speed;
        if (!opts.speedOut) 
            opts.speedOut = opts.speed;

 		opts.slideCount = els.length;
        opts.currSlide = first;
        if (opts.random) {
            opts.nextSlide = opts.currSlide;
            if (++opts.randomIndex == els.length) 
                opts.randomIndex = 0;
            opts.nextSlide = opts.randomMap[opts.randomIndex];
        }
        else
            opts.nextSlide = opts.startingSlide >= (els.length-1) ? 0 : opts.startingSlide+1;

        // fire artificial events
        var e0 = $slides[first];
        if (opts.before.length)
            opts.before[0].apply(e0, [e0, e0, opts, true]);
        if (opts.after.length > 1)
            opts.after[1].apply(e0, [e0, e0, opts, true]);
        
        if (opts.click && !opts.next)
            opts.next = opts.click;
        if (opts.next)
            $(opts.next).bind('click', function(){return advance(els,opts,opts.rev?-1:1)});
        if (opts.prev)
            $(opts.prev).bind('click', function(){return advance(els,opts,opts.rev?1:-1)});
        if (opts.pager)
            buildPager(els,opts);

        // expose fn for adding slides after the show has started
        opts.addSlide = function(newSlide) {
            var $s = $(newSlide), s = $s[0];
            if (!opts.autostopCount)
                opts.countdown++;
            els.push(s);
            if (opts.els) 
                opts.els.push(s); // shuffle needs this
            opts.slideCount = els.length;
            
            $s.css('position','absolute').appendTo($cont);
            
            if (ie6 && opts.cleartype && !opts.cleartypeNoBg)
                clearTypeFix($s);

            if (opts.fit && opts.width) 
                $s.width(opts.width);
            if (opts.fit && opts.height && opts.height != 'auto') 
                $slides.height(opts.height);
            s.cycleH = (opts.fit && opts.height) ? opts.height : $s.height();
            s.cycleW = (opts.fit && opts.width) ? opts.width : $s.width();

            $s.css(opts.cssBefore);

            if (opts.pager)
                $.fn.cycle.createPagerAnchor(els.length-1, s, $(opts.pager), els, opts);
            
            if (typeof opts.onAddSlide == 'function')
                opts.onAddSlide($s);
        };

        if (opts.timeout || opts.continuous)
            this.cycleTimeout = setTimeout(
                function(){go(els,opts,0,!opts.rev)}, 
                opts.continuous ? 10 : opts.timeout + (opts.delay||0));
    });
};

function go(els, opts, manual, fwd) {
    if (opts.busy) return;
    var p = opts.container, curr = els[opts.currSlide], next = els[opts.nextSlide];
    if (p.cycleTimeout === 0 && !manual) 
        return;

    if (!manual && !p.cyclePause && 
        ((opts.autostop && (--opts.countdown <= 0)) ||
        (opts.nowrap && !opts.random && opts.nextSlide < opts.currSlide))) {
        if (opts.end)
            opts.end(opts);
        return;
    }

    if (manual || !p.cyclePause) {
        if (opts.before.length)
            $.each(opts.before, function(i,o) { o.apply(next, [curr, next, opts, fwd]); });
        var after = function() {
            if ($.browser.msie && opts.cleartype)
                this.style.removeAttribute('filter');
            $.each(opts.after, function(i,o) { o.apply(next, [curr, next, opts, fwd]); });
        };

        if (opts.nextSlide != opts.currSlide) {
            opts.busy = 1;
            if (opts.fxFn)
                opts.fxFn(curr, next, opts, after, fwd);
            else if ($.isFunction($.fn.cycle[opts.fx]))
                $.fn.cycle[opts.fx](curr, next, opts, after);
            else
                $.fn.cycle.custom(curr, next, opts, after, manual && opts.fastOnEvent);
        }
        if (opts.random) {
            opts.currSlide = opts.nextSlide;
            if (++opts.randomIndex == els.length) 
                opts.randomIndex = 0;
            opts.nextSlide = opts.randomMap[opts.randomIndex];
        }
        else { // sequence
            var roll = (opts.nextSlide + 1) == els.length;
            opts.nextSlide = roll ? 0 : opts.nextSlide+1;
            opts.currSlide = roll ? els.length-1 : opts.nextSlide-1;
        }
        if (opts.pager)
            $.fn.cycle.updateActivePagerLink(opts.pager, opts.currSlide);
    }
    if (opts.timeout && !opts.continuous)
        p.cycleTimeout = setTimeout(function() { go(els,opts,0,!opts.rev) }, opts.timeout);
    else if (opts.continuous && p.cyclePause) 
        p.cycleTimeout = setTimeout(function() { go(els,opts,0,!opts.rev) }, 10);
};

$.fn.cycle.updateActivePagerLink = function(pager, currSlide) {
    $(pager).find('a').removeClass('activeSlide').filter('a:eq('+currSlide+')').addClass('activeSlide');
};

// advance slide forward or back
function advance(els, opts, val) {
    var p = opts.container, timeout = p.cycleTimeout;
    if (timeout) {
        clearTimeout(timeout);
        p.cycleTimeout = 0;
    }
    if (opts.random && val < 0) {
        // move back to the previously display slide
        opts.randomIndex--;
        if (--opts.randomIndex == -2)
            opts.randomIndex = els.length-2;
        else if (opts.randomIndex == -1)
            opts.randomIndex = els.length-1;
        opts.nextSlide = opts.randomMap[opts.randomIndex];
    }
    else if (opts.random) {
        if (++opts.randomIndex == els.length) 
            opts.randomIndex = 0;
        opts.nextSlide = opts.randomMap[opts.randomIndex];
    }
    else {
        opts.nextSlide = opts.currSlide + val;
        if (opts.nextSlide < 0) {
            if (opts.nowrap) return false;
            opts.nextSlide = els.length - 1;
        }
        else if (opts.nextSlide >= els.length) {
            if (opts.nowrap) return false;
            opts.nextSlide = 0;
        }
    }
    
    if (opts.prevNextClick && typeof opts.prevNextClick == 'function')
        opts.prevNextClick(val > 0, opts.nextSlide, els[opts.nextSlide]);
    go(els, opts, 1, val>=0);
    return false;
};

function buildPager(els, opts) {
    var $p = $(opts.pager);
    $.each(els, function(i,o) {
        $.fn.cycle.createPagerAnchor(i,o,$p,els,opts);
    });
   $.fn.cycle.updateActivePagerLink(opts.pager, opts.startingSlide);
};

$.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) {
    var $a = (typeof opts.pagerAnchorBuilder == 'function')
        ? $(opts.pagerAnchorBuilder(i,el))
        : $('<a href="#">'+(i+1)+'</a>');
    
    // don't reparent if anchor is in the dom
    if ($a.parents('body').length == 0)
        $a.appendTo($p);
        
    $a.bind(opts.pagerEvent, function() {
        opts.nextSlide = i;
        var p = opts.container, timeout = p.cycleTimeout;
        if (timeout) {
            clearTimeout(timeout);
            p.cycleTimeout = 0;
        }            
        if (typeof opts.pagerClick == 'function')
            opts.pagerClick(opts.nextSlide, els[opts.nextSlide]);
        go(els,opts,1,opts.currSlide < i);
        return false;
    });
	if (opts.pauseOnPagerHover)
		$a.hover(function() { opts.container.cyclePause = 1; }, function() { opts.container.cyclePause = 0; } );
};


// this fixes clearType problems in ie6 by setting an explicit bg color
function clearTypeFix($slides) {
    function hex(s) {
        var s = parseInt(s).toString(16);
        return s.length < 2 ? '0'+s : s;
    };
    function getBg(e) {
        for ( ; e && e.nodeName.toLowerCase() != 'html'; e = e.parentNode) {
            var v = $.css(e,'background-color');
            if (v.indexOf('rgb') >= 0 ) { 
                var rgb = v.match(/\d+/g); 
                return '#'+ hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
            }
            if (v && v != 'transparent')
                return v;
        }
        return '#ffffff';
    };
    $slides.each(function() { $(this).css('background-color', getBg(this)); });
};


$.fn.cycle.custom = function(curr, next, opts, cb, immediate) {
    var $l = $(curr), $n = $(next);
    $n.css(opts.cssBefore);
    var speedIn = immediate ? 1 : opts.speedIn;
    var speedOut = immediate ? 1 : opts.speedOut;
    var easeIn = immediate ? null : opts.easeIn;
    var easeOut = immediate ? null : opts.easeOut;
    var fn = function() {$n.animate(opts.animIn, speedIn, easeIn, cb)};
    $l.animate(opts.animOut, speedOut, easeOut, function() {
        if (opts.cssAfter) $l.css(opts.cssAfter);
        if (!opts.sync) fn();
    });
    if (opts.sync) fn();
};

$.fn.cycle.transitions = {
    fade: function($cont, $slides, opts) {
        $slides.not(':eq('+opts.startingSlide+')').css('opacity',0);
        opts.before.push(function() { $(this).show() });
        opts.animIn    = { opacity: 1 };
        opts.animOut   = { opacity: 0 };
        opts.cssBefore = { opacity: 0 };
        opts.cssAfter  = { display: 'none' };
    }
};

$.fn.cycle.ver = function() { return ver; };

// override these globally if you like (they are all optional)
$.fn.cycle.defaults = {
    fx:           'fade', // one of: fade, shuffle, zoom, scrollLeft, etc
    timeout:       4000,  // milliseconds between slide transitions (0 to disable auto advance)
    continuous:    0,     // true to start next transition immediately after current one completes
    speed:         1000,  // speed of the transition (any valid fx speed value)
    speedIn:       null,  // speed of the 'in' transition
    speedOut:      null,  // speed of the 'out' transition
    next:          null,  // id of element to use as click trigger for next slide
    prev:          null,  // id of element to use as click trigger for previous slide
    prevNextClick: null,  // callback fn for prev/next clicks:  function(isNext, zeroBasedSlideIndex, slideElement)
    pager:         null,  // id of element to use as pager container
    pagerClick:    null,  // callback fn for pager clicks:  function(zeroBasedSlideIndex, slideElement)
    pagerEvent:   'click', // event which drives the pager navigation
    pagerAnchorBuilder: null, // callback fn for building anchor links
    before:        null,  // transition callback (scope set to element to be shown)
    after:         null,  // transition callback (scope set to element that was shown)
    end:           null,  // callback invoked when the slideshow terminates (use with autostop or nowrap options)
    easing:        null,  // easing method for both in and out transitions
    easeIn:        null,  // easing for "in" transition
    easeOut:       null,  // easing for "out" transition
    shuffle:       null,  // coords for shuffle animation, ex: { top:15, left: 200 }
    animIn:        null,  // properties that define how the slide animates in
    animOut:       null,  // properties that define how the slide animates out
    cssBefore:     null,  // properties that define the initial state of the slide before transitioning in
    cssAfter:      null,  // properties that defined the state of the slide after transitioning out
    fxFn:          null,  // function used to control the transition
    height:       'auto', // container height
    startingSlide: 0,     // zero-based index of the first slide to be displayed
    sync:          1,     // true if in/out transitions should occur simultaneously
    random:        0,     // true for random, false for sequence (not applicable to shuffle fx)
    fit:           0,     // force slides to fit container
    pause:         0,     // true to enable "pause on hover"
	pauseOnPagerHover: 0, // true to pause when hovering over pager link
    autostop:      0,     // true to end slideshow after X transitions (where X == slide count)
    autostopCount: 0,     // number of transitions (optionally used with autostop to define X)
    delay:         0,     // additional delay (in ms) for first transition (hint: can be negative)
    slideExpr:     null,  // expression for selecting slides (if something other than all children is required)
    cleartype:     0,     // true if clearType corrections should be applied (for IE)
    nowrap:        0,     // true to prevent slideshow from wrapping
    fastOnEvent:   0      // force immediate transition when triggered manually (via pager or prev/next)
};

})(jQuery);


/*
 * jQuery Cycle Plugin Transition Definitions
 * This script is a plugin for the jQuery Cycle Plugin
 * Examples and documentation at: http://malsup.com/jquery/cycle/
 * Copyright (c) 2007-2008 M. Alsup
 * Version:  2.22
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */
(function($) {

//
// These functions define one-time slide initialization for the named
// transitions. To save file size feel free to remove any of these that you 
// don't need.
//

// scrollUp/Down/Left/Right
$.fn.cycle.transitions.scrollUp = function($cont, $slides, opts) {
    $cont.css('overflow','hidden');
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore.top = next.offsetHeight;
        opts.animOut.top = 0-curr.offsetHeight;
    });
    opts.cssFirst = { top: 0 };
    opts.animIn   = { top: 0 };
    opts.cssAfter = { display: 'none' };
};
$.fn.cycle.transitions.scrollDown = function($cont, $slides, opts) {
    $cont.css('overflow','hidden');
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore.top = 0-next.offsetHeight;
        opts.animOut.top = curr.offsetHeight;
    });
    opts.cssFirst = { top: 0 };
    opts.animIn   = { top: 0 };
    opts.cssAfter = { display: 'none' };
};
$.fn.cycle.transitions.scrollLeft = function($cont, $slides, opts) {
    $cont.css('overflow','hidden');
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore.left = next.offsetWidth;
        opts.animOut.left = 0-curr.offsetWidth;
    });
    opts.cssFirst = { left: 0 };
    opts.animIn   = { left: 0 };
};
$.fn.cycle.transitions.scrollRight = function($cont, $slides, opts) {
    $cont.css('overflow','hidden');
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore.left = 0-next.offsetWidth;
        opts.animOut.left = curr.offsetWidth;
    });
    opts.cssFirst = { left: 0 };
    opts.animIn   = { left: 0 };
};
$.fn.cycle.transitions.scrollHorz = function($cont, $slides, opts) {
    $cont.css('overflow','hidden').width();
//    $slides.show();
    opts.before.push(function(curr, next, opts, fwd) {
        $(this).show();
        var currW = curr.offsetWidth, nextW = next.offsetWidth;
        opts.cssBefore = fwd ? { left: nextW } : { left: -nextW };
        opts.animIn.left = 0;
        opts.animOut.left = fwd ? -currW : currW;
        $slides.not(curr).css(opts.cssBefore);
    });
    opts.cssFirst = { left: 0 };
    opts.cssAfter = { display: 'none' }
};
$.fn.cycle.transitions.scrollVert = function($cont, $slides, opts) {
    $cont.css('overflow','hidden');
//    $slides.show();
    opts.before.push(function(curr, next, opts, fwd) {
        $(this).show();
        var currH = curr.offsetHeight, nextH = next.offsetHeight;
        opts.cssBefore = fwd ? { top: -nextH } : { top: nextH };
        opts.animIn.top = 0;
        opts.animOut.top = fwd ? currH : -currH;
        $slides.not(curr).css(opts.cssBefore);
    });
    opts.cssFirst = { top: 0 };
    opts.cssAfter = { display: 'none' }
};

// slideX/slideY
$.fn.cycle.transitions.slideX = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        $(curr).css('zIndex',1);
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssBefore = { zIndex: 2 };
    opts.animIn  = { width: 'show' };
    opts.animOut = { width: 'hide' };
};
$.fn.cycle.transitions.slideY = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        $(curr).css('zIndex',1);
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssBefore = { zIndex: 2 };
    opts.animIn  = { height: 'show' };
    opts.animOut = { height: 'hide' };
};

// shuffle
$.fn.cycle.transitions.shuffle = function($cont, $slides, opts) {
    var w = $cont.css('overflow', 'visible').width();
    $slides.css({left: 0, top: 0});
    opts.before.push(function() { $(this).show() });
    opts.speed = opts.speed / 2; // shuffle has 2 transitions        
    opts.random = 0;
    opts.shuffle = opts.shuffle || {left:-w, top:15};
    opts.els = [];
    for (var i=0; i < $slides.length; i++)
        opts.els.push($slides[i]);

    for (var i=0; i < opts.startingSlide; i++)
        opts.els.push(opts.els.shift());

    // custom transition fn (hat tip to Benjamin Sterling for this bit of sweetness!)
    opts.fxFn = function(curr, next, opts, cb, fwd) {
        var $el = fwd ? $(curr) : $(next);
        $el.animate(opts.shuffle, opts.speedIn, opts.easeIn, function() {
            fwd ? opts.els.push(opts.els.shift()) : opts.els.unshift(opts.els.pop());
            if (fwd) 
                for (var i=0, len=opts.els.length; i < len; i++)
                    $(opts.els[i]).css('z-index', len-i);
            else {
                var z = $(curr).css('z-index');
                $el.css('z-index', parseInt(z)+1);
            }
            $el.animate({left:0, top:0}, opts.speedOut, opts.easeOut, function() {
                $(fwd ? this : curr).hide();
                if (cb) cb();
            });
        });
    };
    opts.onAddSlide = function($s) { $s.hide(); };
};

// turnUp/Down/Left/Right
$.fn.cycle.transitions.turnUp = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore.top = next.cycleH;
        opts.animIn.height = next.cycleH;
    });
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssFirst  = { top: 0 };
    opts.cssBefore = { height: 0 };
    opts.animIn    = { top: 0 };
    opts.animOut   = { height: 0 };
    opts.cssAfter  = { display: 'none' };
};
$.fn.cycle.transitions.turnDown = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.animIn.height = next.cycleH;
        opts.animOut.top   = curr.cycleH;
    });
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssFirst  = { top: 0 };
    opts.cssBefore = { top: 0, height: 0 };
    opts.animOut   = { height: 0 };
    opts.cssAfter  = { display: 'none' };
};
$.fn.cycle.transitions.turnLeft = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore.left = next.cycleW;
        opts.animIn.width = next.cycleW;
    });
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssBefore = { width: 0 };
    opts.animIn    = { left: 0 };
    opts.animOut   = { width: 0 };
    opts.cssAfter  = { display: 'none' };
};
$.fn.cycle.transitions.turnRight = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.animIn.width = next.cycleW;
        opts.animOut.left = curr.cycleW;
    });
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssBefore = { left: 0, width: 0 };
    opts.animIn    = { left: 0 };
    opts.animOut   = { width: 0 };
    opts.cssAfter  = { display: 'none' };
};

// zoom
$.fn.cycle.transitions.zoom = function($cont, $slides, opts) {
    opts.cssFirst = { top:0, left: 0 }; 
    opts.cssAfter = { display: 'none' };
    
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore = { width: 0, height: 0, top: next.cycleH/2, left: next.cycleW/2 };
        opts.cssAfter  = { display: 'none' };
        opts.animIn    = { top: 0, left: 0, width: next.cycleW, height: next.cycleH };
        opts.animOut   = { width: 0, height: 0, top: curr.cycleH/2, left: curr.cycleW/2 };
        $(curr).css('zIndex',2);
        $(next).css('zIndex',1);
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
};

// fadeZoom
$.fn.cycle.transitions.fadeZoom = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore = { width: 0, height: 0, opacity: 1, left: next.cycleW/2, top: next.cycleH/2, zIndex: 1 };
        opts.animIn    = { top: 0, left: 0, width: next.cycleW, height: next.cycleH };
    });    
    opts.animOut  = { opacity: 0 };
    opts.cssAfter = { zIndex: 0 };
};

// blindX
$.fn.cycle.transitions.blindX = function($cont, $slides, opts) {
    var w = $cont.css('overflow','hidden').width();
    $slides.show();
    opts.before.push(function(curr, next, opts) {
        $(curr).css('zIndex',1);
    });    
    opts.cssBefore = { left: w, zIndex: 2 };
    opts.cssAfter = { zIndex: 1 };
    opts.animIn = { left: 0 };
    opts.animOut  = { left: w };
};
// blindY
$.fn.cycle.transitions.blindY = function($cont, $slides, opts) {
    var h = $cont.css('overflow','hidden').height();
    $slides.show();
    opts.before.push(function(curr, next, opts) {
        $(curr).css('zIndex',1);
    });    
    opts.cssBefore = { top: h, zIndex: 2 };
    opts.cssAfter = { zIndex: 1 };
    opts.animIn = { top: 0 };
    opts.animOut  = { top: h };
};
// blindZ
$.fn.cycle.transitions.blindZ = function($cont, $slides, opts) {
    var h = $cont.css('overflow','hidden').height();
    var w = $cont.width();
    $slides.show();
    opts.before.push(function(curr, next, opts) {
        $(curr).css('zIndex',1);
    });    
    opts.cssBefore = { top: h, left: w, zIndex: 2 };
    opts.cssAfter = { zIndex: 1 };
    opts.animIn = { top: 0, left: 0 };
    opts.animOut  = { top: h, left: w };
};

// growX - grow horizontally from centered 0 width
$.fn.cycle.transitions.growX = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore = { left: this.cycleW/2, width: 0, zIndex: 2 };
        opts.animIn = { left: 0, width: this.cycleW };
        opts.animOut = { left: 0 };
        $(curr).css('zIndex',1);
    });    
    opts.onAddSlide = function($s) { $s.hide().css('zIndex',1); };
};
// growY - grow vertically from centered 0 height
$.fn.cycle.transitions.growY = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore = { top: this.cycleH/2, height: 0, zIndex: 2 };
        opts.animIn = { top: 0, height: this.cycleH };
        opts.animOut = { top: 0 };
        $(curr).css('zIndex',1);
    });    
    opts.onAddSlide = function($s) { $s.hide().css('zIndex',1); };
};

// curtainX - squeeze in both edges horizontally
$.fn.cycle.transitions.curtainX = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore = { left: next.cycleW/2, width: 0, zIndex: 1, display: 'block' };
        opts.animIn = { left: 0, width: this.cycleW };
        opts.animOut = { left: curr.cycleW/2, width: 0 };
        $(curr).css('zIndex',2);
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssAfter = { zIndex: 1, display: 'none' };
};
// curtainY - squeeze in both edges vertically
$.fn.cycle.transitions.curtainY = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore = { top: next.cycleH/2, height: 0, zIndex: 1, display: 'block' };
        opts.animIn = { top: 0, height: this.cycleH };
        opts.animOut = { top: curr.cycleH/2, height: 0 };
        $(curr).css('zIndex',2);
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssAfter = { zIndex: 1, display: 'none' };
};

// cover - curr slide covered by next slide
$.fn.cycle.transitions.cover = function($cont, $slides, opts) {
    var d = opts.direction || 'left';
    var w = $cont.css('overflow','hidden').width();
    var h = $cont.height();
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore = opts.cssBefore || {};
        opts.cssBefore.zIndex = 2;
        opts.cssBefore.display = 'block';
        
        if (d == 'right') 
            opts.cssBefore.left = -w;
        else if (d == 'up')    
            opts.cssBefore.top = h;
        else if (d == 'down')  
            opts.cssBefore.top = -h;
        else
            opts.cssBefore.left = w;
        $(curr).css('zIndex',1);
    });    
    if (!opts.animIn)  opts.animIn = { left: 0, top: 0 };
    if (!opts.animOut) opts.animOut = { left: 0, top: 0 };
    opts.cssAfter = opts.cssAfter || {};
    opts.cssAfter.zIndex = 2;
    opts.cssAfter.display = 'none';
};

// uncover - curr slide moves off next slide
$.fn.cycle.transitions.uncover = function($cont, $slides, opts) {
    var d = opts.direction || 'left';
    var w = $cont.css('overflow','hidden').width();
    var h = $cont.height();
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore.display = 'block';
        if (d == 'right') 
            opts.animOut.left = w;
        else if (d == 'up')    
            opts.animOut.top = -h;
        else if (d == 'down')  
            opts.animOut.top = h;
        else
            opts.animOut.left = -w;
        $(curr).css('zIndex',2);
        $(next).css('zIndex',1);
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
    if (!opts.animIn)  opts.animIn = { left: 0, top: 0 };
    opts.cssBefore = opts.cssBefore || {};
    opts.cssBefore.top = 0;
    opts.cssBefore.left = 0;
    
    opts.cssAfter = opts.cssAfter || {};
    opts.cssAfter.zIndex = 1;
    opts.cssAfter.display = 'none';
};

// toss - move top slide and fade away
$.fn.cycle.transitions.toss = function($cont, $slides, opts) {
    var w = $cont.css('overflow','visible').width();
    var h = $cont.height();
    opts.before.push(function(curr, next, opts) {
        $(curr).css('zIndex',2);
        opts.cssBefore.display = 'block'; 
        // provide default toss settings if animOut not provided
        if (!opts.animOut.left && !opts.animOut.top)
            opts.animOut = { left: w*2, top: -h/2, opacity: 0 };
        else
            opts.animOut.opacity = 0;
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssBefore = { left: 0, top: 0, zIndex: 1, opacity: 1 };
    opts.animIn = { left: 0 };
    opts.cssAfter = { zIndex: 2, display: 'none' };
};

// wipe - clip animation
$.fn.cycle.transitions.wipe = function($cont, $slides, opts) {
    var w = $cont.css('overflow','hidden').width();
    var h = $cont.height();
    opts.cssBefore = opts.cssBefore || {};
    var clip;
    if (opts.clip) {
        if (/l2r/.test(opts.clip))
            clip = 'rect(0px 0px '+h+'px 0px)';
        else if (/r2l/.test(opts.clip))
            clip = 'rect(0px '+w+'px '+h+'px '+w+'px)';
        else if (/t2b/.test(opts.clip))
            clip = 'rect(0px '+w+'px 0px 0px)';
        else if (/b2t/.test(opts.clip))
            clip = 'rect('+h+'px '+w+'px '+h+'px 0px)';
        else if (/zoom/.test(opts.clip)) {
            var t = parseInt(h/2);
            var l = parseInt(w/2);
            clip = 'rect('+t+'px '+l+'px '+t+'px '+l+'px)';
        }
    }
    
    opts.cssBefore.clip = opts.cssBefore.clip || clip || 'rect(0px 0px 0px 0px)';
    
    var d = opts.cssBefore.clip.match(/(\d+)/g);
    var t = parseInt(d[0]), r = parseInt(d[1]), b = parseInt(d[2]), l = parseInt(d[3]);
    
    opts.before.push(function(curr, next, opts) {
        if (curr == next) return;
        var $curr = $(curr).css('zIndex',2);
        var $next = $(next).css({
            zIndex:  3,
            display: 'block'
        });
        
        var step = 1, count = parseInt((opts.speedIn / 13)) - 1;
        function f() {
            var tt = t ? t - parseInt(step * (t/count)) : 0;
            var ll = l ? l - parseInt(step * (l/count)) : 0;
            var bb = b < h ? b + parseInt(step * ((h-b)/count || 1)) : h;
            var rr = r < w ? r + parseInt(step * ((w-r)/count || 1)) : w;
            $next.css({ clip: 'rect('+tt+'px '+rr+'px '+bb+'px '+ll+'px)' });
            (step++ <= count) ? setTimeout(f, 13) : $curr.css('display', 'none');
        }
        f();
    });    
    opts.cssAfter  = { };
    opts.animIn    = { left: 0 };
    opts.animOut   = { left: 0 };
};

})(jQuery);
/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-06-20 03:23:36 +0200 (Mi, 20 Jun 2007) $
 * $Rev: 2110 $
 *
 * Version 2.1
 */

(function($){

/**
 * The bgiframe is chainable and applies the iframe hack to get
 * around zIndex issues in IE6. It will only apply itself in IE
 * and adds a class to the iframe called 'bgiframe'. The iframe
 * is appeneded as the first child of the matched element(s)
 * with a tabIndex and zIndex of -1.
 *
 * By default the plugin will take borders, sized with pixel units,
 * into account. If a different unit is used for the border's width,
 * then you will need to use the top and left settings as explained below.
 *
 * NOTICE: This plugin has been reported to cause perfromance problems
 * when used on elements that change properties (like width, height and
 * opacity) a lot in IE6. Most of these problems have been caused by
 * the expressions used to calculate the elements width, height and
 * borders. Some have reported it is due to the opacity filter. All
 * these settings can be changed if needed as explained below.
 *
 * @example $('div').bgiframe();
 * @before <div><p>Paragraph</p></div>
 * @result <div><iframe class="bgiframe".../><p>Paragraph</p></div>
 *
 * @param Map settings Optional settings to configure the iframe.
 * @option String|Number top The iframe must be offset to the top
 * 		by the width of the top border. This should be a negative
 *      number representing the border-top-width. If a number is
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used.
 * 		By default the value is "auto" which will use an expression
 * 		to get the border-top-width if it is in pixels.
 * @option String|Number left The iframe must be offset to the left
 * 		by the width of the left border. This should be a negative
 *      number representing the border-left-width. If a number is
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used.
 * 		By default the value is "auto" which will use an expression
 * 		to get the border-left-width if it is in pixels.
 * @option String|Number width This is the width of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetWidth.
 * @option String|Number height This is the height of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetHeight.
 * @option Boolean opacity This is a boolean representing whether or not
 * 		to use opacity. If set to true, the opacity of 0 is applied. If
 *		set to false, the opacity filter is not applied. Default: true.
 * @option String src This setting is provided so that one could change
 *		the src of the iframe to whatever they need.
 *		Default: "javascript:false;"
 *
 * @name bgiframe
 * @type jQuery
 * @cat Plugins/bgiframe
 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 */
$.fn.bgIframe = $.fn.bgiframe = function(s) {
	// This is only for IE6
	if ( $.browser.msie && parseInt($.browser.version) <= 6 ) {
		s = $.extend({
			top     : 'auto', // auto == .currentStyle.borderTopWidth
			left    : 'auto', // auto == .currentStyle.borderLeftWidth
			width   : 'auto', // auto == offsetWidth
			height  : 'auto', // auto == offsetHeight
			opacity : true,
			src     : 'javascript:false;'
		}, s || {});
		var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
		    html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
		               'style="display:block;position:absolute;z-index:-1;'+
			               (s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
					       'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
					       'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
					       'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
					       'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
					'"/>';
		return this.each(function() {
			if ( $('> iframe.bgiframe', this).length == 0 )
				this.insertBefore( document.createElement(html), this.firstChild );
		});
	}
	return this;
};

// Add browser.version if it doesn't exist
if (!$.browser.version)
	$.browser.version = navigator.userAgent.toLowerCase().match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)[1];

})(jQuery);
$.fn.jForms = 
function(options)
{
	var lastKeypress = 0;
    var keyBuffer = '';
    var self = this;
    var defaults = {
	imagePath : '/niceforms/default/',
	listSize:20
	}	
	if($.browser.safari){return false;}

	var opts = $.extend(defaults, options);
	var imagePath = opts.imagePath	
	
	//preload images
	var images = [imagePath + "button_left_xon.gif", imagePath + "button_right_xon.gif", 
	imagePath + "input_left_xon.gif", imagePath + "input_right_xon.gif",
	imagePath + "txtarea_bl_xon.gif", imagePath + "txtarea_br_xon.gif", 
	imagePath + "txtarea_cntr_xon.gif", imagePath + "txtarea_l_xon.gif", imagePath + "txtarea_tl_xon.gif", imagePath + "txtarea_tr_xon.gif"]
	var imgs = new Array();
	for(var i = 0; i<images.length; i++)
	{
		imgs[i] = $("<img>").attr("src", images[i]);
	}

	$(self).attr('autocomplete','off').addClass('niceforms');
	
	//text and passwords
	$(':text,:password',self).each(function()
	{
		$(this).addClass('textinput').before('<img src = "'+imagePath+'input_left.gif" class="inputCorner" />').after('<img src="'+imagePath+'input_right.gif" class="inputCorner" />').focus(function()
		{
			$(this).css('background-position','bottom').prev().attr('src',imagePath+'input_left_xon.gif')
			$(this).next().attr('src',imagePath+'input_right_xon.gif');

		}).blur(function()
		{
			$(this).css('background-position','top').prev().attr('src',imagePath+'input_left.gif')
			$(this).next().attr('src',imagePath+'input_right.gif');
		});	
	});
	
			//select boxes
$('select',self).each(function ()
{
	$('body').append('<ul id = "'+this.id+'_fake_list" class="fake_list"></ul>');
	$(this).children().each(function()
	{
		$('#'+$(this).parent().attr('id')+'_fake_list').append('<li>'+$(this).text()+'</li>');
	});
	$('#'+this.id+'_fake_list').css('height',($('#'+this.id+'_fake_list li:first').height()+4)*($('#'+this.id+'_fake_list li').size()<opts.listSize?$('#'+this.id+'_fake_list li').size():opts.listSize)).css('width',$(this).width()+18).toggle();
	
	$('#'+this.id+'_fake_list > li').hover(function(){$(this).addClass('selected')},function(){$(this).removeClass('selected');}).each(function(i)
	{
		$(this).click(function(){
		var id = $(this).parent().attr('id');
		$('#'+id).toggle();
	    $('#'+id.replace('_list','')).attr('value',$(this).text());
		$('#'+id.replace('_fake_list','')).attr('selectedIndex',i).change();
		$('#'+id+' >  li').removeClass('selected');
		$(this).addClass('selected');	
	});
	});

$(this).before('<div class="selectArea" style="width:'+($(this).width()+43)+'px"><div class="left"></div><div class="right"><a class="selectButton" href="javascript:;" onclick="$(\'#'+this.id+'_fake\').focus().click()"></a></div><input type = "text" class="center" style="width:'+($(this).width())+'px;cursor:default" id="'+this.id+'_fake"  value="'+this[this.selectedIndex].text+'"  /></div>').css('position','absolute').css('left','-6000px');

	$('#'+this.id+'_fake').click(function(){
		$('#'+this.id+'_list').focus();
		$('#'+this.id+'_list').css('left',$(this).offset().left-8);
		
		if(($('#'+this.id+'_list').height()+$(this).offset().top -document.documentElement.scrollTop) > $(window).height())
		{
			$('#'+this.id+'_list').css('top',$(this).offset().top-$('#'+this.id+'_list').height()-4);
		}
		else
		{
			$('#'+this.id+'_list').css('top',$(this).offset().top+$(this).height()+4);
		}
		$('#'+this.id+'_list > li').removeClass('selected');
		$('#'+this.id+'_list > li').get($('#'+this.id.replace('_fake','')).attr('selectedIndex')).className='selected';

		
		$('.fake_list:visible:not(#'+this.id+'_list)').toggle();
		$list = $('#'+this.id+'_list');	
		$list.toggle();		
		var offSet = (($('.selected', $list).length>0? $('.selected', $list).offset().top:0)- $list.offset().top);
		$list.animate({scrollTop: offSet});
		}).css('font-size',$(this).css('font-size')).css('padding','2px 0px 2px 2px').keyup(function(e)
		{
			var pressedKey = e.charCode || e.keyCode || -1;
			var $dd = $('#'+this.id.replace('_fake',''));
			$('#'+this.id+'_list > li').removeClass('selected');
			switch(pressedKey)
			{
				//down
				case 40:						
					var curr = ($dd.attr('selectedIndex')+1>=$('option',$dd).length?0:$dd.attr('selectedIndex')+1);
				break;
				case 38:						
					var curr = ($dd.attr('selectedIndex')-1<0?$('option',$dd).length-1:$dd.attr('selectedIndex')-1);						
				break;
				case 13:
					$('#'+this.id+'_list').toggle();
					return false;
				break;
				default:
				var t = new Date();
				if(t.getTime()-lastKeypress>1000)
				{
					lastKeypress=t.getTime();
					keyBuffer ='';
				}
					keyBuffer +=String.fromCharCode(pressedKey).toLowerCase();
					curr=-1;
					$('#'+this.id+'_list > li').each(function(i)
					{
						if($(this).text().toLowerCase().indexOf(keyBuffer)==0&&curr==-1)
						{
							curr = i;
							return;
						}
					});
					break;
			}
			if(curr==-1)
			{
				curr=0;
			}
			$($('#'+this.id+'_list > li').get(curr)).addClass('selected').focus();
			$list = $('#'+this.id+'_list');
			var offSet = (($('.selected', $list).length>0? $('.selected', $list).offset().top:0)- $list.offset().top);
			$list.attr('scrollTop',offSet);
			$dd.attr('selectedIndex',curr).change();
			$(this).attr('value', $($('#'+this.id+'_list > li').get(curr)).text());
			return false;
						
		}).focus(function()
		{
			$(document).keypress(function(e)
			{
				var pressedKey = e.charCode || e.keyCode || -1;
				if(pressedKey==13)
				{
					return false;
				}
			});
		}).blur(function()
		{
			$(document).unbind('keypress').unbind('click');
		});

});

	//checkboxes
	$(':checkbox',self).each(function()
	{
		$(this).before('<div style="margin: 1px;" id="'+this.id+'_fake"></div>');
		$(this).addClass('outtaHere');
		this.checked?$('label[for='+this.id+']').addClass('chosen'):'';
		$('#'+this.id+'_fake').addClass(this.checked?'checkboxAreaChecked':'checkboxArea').click(function()
		{
			$('label[for='+this.id.replace('_fake','')+']').click();	
			$('#'+this.id.replace('_fake','')).attr('checked')?$('#'+this.id.replace('_fake','')).attr('checked',''):$('#'+this.id.replace('_fake','')).attr('checked','checked');
		});
		$('label[for='+this.id+']').click(function()
		{
			//these are backwards on purpose -click functions are called before the checkbox is selected
			$('#'+$(this).attr('for')).attr('checked')?$(this).removeClass('chosen'):$(this).addClass('chosen');
			$('#'+$(this).attr('for')+'_fake').addClass($('#'+$(this).attr('for')).attr('checked')?'checkboxArea':'checkboxAreaChecked').removeClass($('#'+$(this).attr('for')).attr('checked')?'checkboxAreaChecked':'checkboxArea');
		});
		
	});
	//radios
	$(':radio',self).each(function()
	{
		$(this).after('<div style="margin: 1px;" id="'+this.id+'_fake"></div>').addClass('outtaHere');
		this.checked?$('label[for='+this.id+']').addClass('chosen'):'';
		$('#'+this.id+'_fake').addClass(this.checked?'radioAreaChecked':'radioArea').click(function()
		{
			$(':radio[name='+$('#'+this.id.replace('_fake','')).attr('name')+']').each(function()
			{
				this.checked=false;	
			});
			$('#'+this.id.replace('_fake','')).attr('checked','checked');
			$('label[for='+this.id.replace('_fake','')+']').click();
		});	
		$('label[for='+this.id+']').click(function()
		{					
			$(':radio[name='+$('#'+$(this).attr('for')).attr('name')+']').each(function()
			{
				$('label[for='+this.id+']').removeClass('chosen');
				$('#'+this.id+'_fake').addClass('radioArea').removeClass('radioAreaChecked');
				$('label[for='+this.id.replace('_fake','')+']').removeClass('chosen');
			});
			$(this).addClass('chosen');	
			$('#'+$(this).attr('for')+'_fake').addClass('radioAreaChecked');	

		})
	});
	//text areas
	$('textarea',self).each(function()
	{
		$(this).replaceWith('<div style="width: '+($(this).width()+20)+'px; height: '+($(this).height()+20)+'px;" class="txtarea" id = "'+this.id+'_fake"><div class="tr"><img src="/niceforms/default/txtarea_tl.gif" class="txt_corner"></div><div class="cntr"><div style="height: '+($(this).height()+10)+'px;" class="cntr_l"></div></div><div class="br"><img src="'+imagePath+'txtarea_bl.gif" class="txt_corner"></div></div>');
		$('#'+this.id+'_fake .cntr').append($(this));
		
	}).focus(function()
	{
		$('#'+this.id+'_fake .tr').removeClass('tr').addClass('tr_xon');
		$('#'+this.id+'_fake .br').removeClass('br').addClass('br_xon');
		$('#'+this.id+'_fake .cntr').removeClass('cntr').addClass('cntr_xon');
		$('#'+this.id+'_fake .cntr_l').removeClass('cntr_').addClass('cntr_l_xon');
		$('#'+this.id+'_fake img:first').attr('src',imagePath+'txtarea_tl_xon.gif');
		$('#'+this.id+'_fake img:last').attr('src',imagePath+'txtarea_bl_xon.gif');
	}).blur(function()
	{
		$('#'+this.id+'_fake .tr_xon').addClass('tr').removeClass('tr_xon');
		$('#'+this.id+'_fake .br_xon').addClass('br').removeClass('br_xon');
		$('#'+this.id+'_fake .cntr_xon').addClass('cntr').removeClass('cntr_xon');
		$('#'+this.id+'_fake .cntr_l_xon').addClass('cntr_').removeClass('cntr_l_xon');
		$('#'+this.id+'_fake img:first').attr('src',imagePath+'txtarea_tl.gif');
		$('#'+this.id+'_fake img:last').attr('src',imagePath+'txtarea_bl.gif');
	});
	
	$(':button,:submit',self).each(function()
	{
		$(this).before('<img class="buttonImg" src="'+imagePath+'button_left.gif">').after('<img class="buttonImg" src="'+imagePath+'button_right.gif">').addClass('buttonSubmit').hover(function()
		{
			$(this).prev().attr('src',imagePath+'button_left_xon.gif');
			$(this).next().attr('src',imagePath+'button_right_xon.gif');
			$(this).addClass('buttonSubmitHovered').removeClass('buttonSubmit');
		},
	 function()
	 {
			$(this).prev().attr('src',imagePath+'button_left.gif');
			$(this).next().attr('src',imagePath+'button_right.gif');
			$(this).removeClass('buttonSubmitHovered').addClass('buttonSubmit');
	});
	});
	return self;
}/*
 * jQuery Tooltip plugin 1.3
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-tooltip/
 * http://docs.jquery.com/Plugins/Tooltip
 *
 * Copyright (c) 2006 - 2008 Jörn Zaefferer
 *
 * $Id: jquery.tooltip.js 5741 2008-06-21 15:22:16Z joern.zaefferer $
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

;(function($) {

		// the tooltip element
	var helper = {},
		// the current tooltipped element
		current,
		// the title of the current element, used for restoring
		title,
		// timeout id for delayed tooltips
		tID,
		// IE 5.5 or 6
		IE = $.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent),
		// flag for mouse tracking
		track = false;

	$.tooltip = {
		blocked: false,
		defaults: {
			delay: 200,
			fade: false,
			showURL: true,
			extraClass: "",
			top: 15,
			left: 15,
			id: "tooltip"
		},
		block: function() {
			$.tooltip.blocked = !$.tooltip.blocked;
		}
	};

	$.fn.extend({
		tooltip: function(settings) {
			settings = $.extend({}, $.tooltip.defaults, settings);
			createHelper(settings);
			return this.each(function() {
					$.data(this, "tooltip", settings);
					this.tOpacity = helper.parent.css("opacity");
					// copy tooltip into its own expando and remove the title
					this.tooltipText = this.title;
					$(this).removeAttr("title");
					// also remove alt attribute to prevent default tooltip in IE
					this.alt = "";
				})
				.mouseover(save)
				.mouseout(hide)
				.click(hide);
		},
		fixPNG: IE ? function() {
			return this.each(function () {
				var image = $(this).css('backgroundImage');
				if (image.match(/^url\(["']?(.*\.png)["']?\)$/i)) {
					image = RegExp.$1;
					$(this).css({
						'backgroundImage': 'none',
						'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
					}).each(function () {
						var position = $(this).css('position');
						if (position != 'absolute' && position != 'relative')
							$(this).css('position', 'relative');
					});
				}
			});
		} : function() { return this; },
		unfixPNG: IE ? function() {
			return this.each(function () {
				$(this).css({'filter': '', backgroundImage: ''});
			});
		} : function() { return this; },
		hideWhenEmpty: function() {
			return this.each(function() {
				$(this)[ $(this).html() ? "show" : "hide" ]();
			});
		},
		url: function() {
			return this.attr('href') || this.attr('src');
		}
	});

	function createHelper(settings) {
		// there can be only one tooltip helper
		if( helper.parent )
			return;
		// create the helper, h3 for title, div for url
		helper.parent = $('<div id="' + settings.id + '"><div class="title"><h3></h3></div><div class="body"></div><div class="url"></div></div>')
			// add to document
			.appendTo(document.body)
			// hide it at first
			.hide();

		// apply bgiframe if available
		if ( $.fn.bgiframe )
			helper.parent.bgiframe();

		// save references to title and url elements
		helper.title = $('h3', helper.parent);
		helper.body = $('div.body', helper.parent);
		helper.url = $('div.url', helper.parent);
	}

	function settings(element) {
		return $.data(element, "tooltip");
	}

	// main event handler to start showing tooltips
	function handle(event) {
		// show helper, either with timeout or on instant
		if( settings(this).delay )
			tID = setTimeout(show, settings(this).delay);
		else
			show();

		// if selected, update the helper position when the mouse moves
		track = !!settings(this).track;
		$(document.body).bind('mousemove', update);

		// update at least once
		update(event);
	}

	// save elements title before the tooltip is displayed
	function save() {
		// if this is the current source, or it has no title (occurs with click event), stop
		if ( $.tooltip.blocked || this == current || (!this.tooltipText && !settings(this).bodyHandler) )
			return;

		// save current
		current = this;
		title = this.tooltipText;

		if ( settings(this).bodyHandler ) {
			helper.title.hide();
			var bodyContent = settings(this).bodyHandler.call(this);
			if (bodyContent.nodeType || bodyContent.jquery) {
				helper.body.empty().append(bodyContent)
			} else {
				helper.body.html( bodyContent );
			}
			helper.body.show();
		} else if ( settings(this).showBody ) {
			var parts = title.split(settings(this).showBody);
			helper.title.html(parts.shift()).show();
			helper.body.empty();
			for(var i = 0, part; (part = parts[i]); i++) {
				if(i > 0)
					helper.body.append("<br/>");
				part = part.replace(/%{%/g, "<");
				part = part.replace(/%}%/g, ">");
				helper.body.append(part);
			}
			helper.body.hideWhenEmpty();
		} else {
			helper.title.html(title).show();
			helper.body.hide();
		}

		// if element has href or src, add and show it, otherwise hide it
		if( settings(this).showURL && $(this).url() )
			helper.url.html( $(this).url().replace('http://', '') ).show();
		else
			helper.url.hide();

		// add an optional class for this tip
		helper.parent.addClass(settings(this).extraClass);

		// fix PNG background for IE
		if (settings(this).fixPNG )
			helper.parent.fixPNG();

		handle.apply(this, arguments);
	}

	// delete timeout and show helper
	function show() {
		tID = null;
		if ((!IE || !$.fn.bgiframe) && settings(current).fade) {
			if (helper.parent.is(":animated"))
				helper.parent.stop().show().fadeTo(settings(current).fade, current.tOpacity);
			else
				helper.parent.is(':visible') ? helper.parent.fadeTo(settings(current).fade, current.tOpacity) : helper.parent.fadeIn(settings(current).fade);
		} else {
			helper.parent.show();
		}
		update();
	}

	/**
	 * callback for mousemove
	 * updates the helper position
	 * removes itself when no current element
	 */
	function update(event)	{
		if($.tooltip.blocked)
			return;

		if (event && event.target.tagName == "OPTION") {
			return;
		}

		// stop updating when tracking is disabled and the tooltip is visible
		if ( !track && helper.parent.is(":visible")) {
			$(document.body).unbind('mousemove', update)
		}

		// if no current element is available, remove this listener
		if( current == null ) {
			$(document.body).unbind('mousemove', update);
			return;
		}

		// remove position helper classes
		helper.parent.removeClass("viewport-right").removeClass("viewport-bottom");

		var left = helper.parent[0].offsetLeft;
		var top = helper.parent[0].offsetTop;
		if (event) {
			// position the helper 15 pixel to bottom right, starting from mouse position
			left = event.pageX + settings(current).left;
			top = event.pageY + settings(current).top;
			var right='auto';
			if (settings(current).positionLeft) {
				right = $(window).width() - left;
				left = 'auto';
			}
			helper.parent.css({
				left: left,
				right: right,
				top: top
			});
		}

		var v = viewport(),
			h = helper.parent[0];
		// check horizontal position
		if (v.x + v.cx < h.offsetLeft + h.offsetWidth) {
			left -= h.offsetWidth + 20 + settings(current).left;
			helper.parent.css({left: left + 'px'}).addClass("viewport-right");
		}
		// check vertical position
		if (v.y + v.cy < h.offsetTop + h.offsetHeight) {
			top -= h.offsetHeight + 20 + settings(current).top;
			helper.parent.css({top: top + 'px'}).addClass("viewport-bottom");
		}
	}

	function viewport() {
		return {
			x: $(window).scrollLeft(),
			y: $(window).scrollTop(),
			cx: $(window).width(),
			cy: $(window).height()
		};
	}

	// hide helper and restore added classes and the title
	function hide(event) {
		if($.tooltip.blocked)
			return;
		// clear timeout if possible
		if(tID)
			clearTimeout(tID);
		// no more current element
		current = null;

		var tsettings = settings(this);
		function complete() {
			helper.parent.removeClass( tsettings.extraClass ).hide().css("opacity", "");
		}
		if ((!IE || !$.fn.bgiframe) && tsettings.fade) {
			if (helper.parent.is(':animated'))
				helper.parent.stop().fadeTo(tsettings.fade, 0, complete);
			else
				helper.parent.stop().fadeOut(tsettings.fade, complete);
		} else
			complete();

		if( settings(this).fixPNG )
			helper.parent.unfixPNG();
	}

})(jQuery);
/**
* jAlert v.1.0.0
* Copyright (c) 2008 Julian Castaneda
* http://www.smooka.com/blog/
* Requires: jQuery 1.2+
*/

(function($) {
    $.fn.jAlert = function (msg, type, uid, alert_box_width, yoffset)
    {
        var tmpobj = this;
		var overlay = 0;
				
		if (uid == undefined)
		{	//generate an unique ID
			var d = new Date();
			var uid = d.getMonth()+""+d.getDate()+""+d.getHours()+""+d.getMinutes()+""+d.getSeconds();
		}

		if ($('#jalert_box_cont_'+uid).css('display') == 'block')
		{
			return;
		}
		
        if (!type) {
            // set type to a default warning
            type = 'warning';
        }

        if (!alert_box_width) {
            //set default width of alert box
            alert_box_width = 350;
        }

        if (!yoffset) {
            //set default y offset of alert box
            yoffset = 0;
        }
		
		if (overlay==1) {
			$('<div id="jalert_overlay_'+uid+'"></div>').prependTo('body');
				var overlayWidth = $(window).width();
				var overlayHeight = $(document).height();
				var winHeight =  $(window).height();
				$("#jalert_overlay_"+uid).css({
											  top: 0, 
											  left: 0, 
											  width: overlayWidth, 
											  height: winHeight, 
											  position: "fixed",
											  display: "block",
											  background: "#000",
											  zIndex: "1000"
										  });
				$("#jalert_overlay_"+uid).css("opacity", 0.9);
		}
		

        //create a prepend the alert box to the container
       //$('<div class="msg-box-cont msg-'+type+'" id="jalert_box_cont_'+uid+'"><table width="100%" border="0" cellpadding="0" cellspacing="0"><tr><td><div class="msg-text"><div class="msg-icon msg-icon-'+type+'"></div>'+msg+'</div></td><td width="21" valign="top"><div class="msg-btn close-'+type+'"></div></td></tr></table></div>').appendTo('body');
		var boxtitle = 'Informacja';
		if(type=='fatal') boxtitle = 'Błąd';
		$('<div class="msg-box-cont msg-'+type+'" id="jalert_box_cont_'+uid+'" style="text-align: left; z-index: 999999999"><p style="text-align: left; padding: 10px 15px; color: #be0d51; font-size: 25px; font-family: arial; font-weight: bold; font-style: italic">'+boxtitle+'</p><div style="padding: 0pt 15px; font-size: 14px;">'+msg+'</div><div style="text-align: right; padding: 5px 15px;"><div class="msg-btn close-'+type+'"></div></div></div>').appendTo('body');

        $("#jalert_box_cont_"+uid).width(alert_box_width);

		alignCenter();
		
        //get the y (top) position of the container
		//var top=this.y() + yoffset;

        //$("#jalert_box_cont_"+uid).css("top",top+"px");
		
		$("#jalert_box_cont_"+uid).fadeIn(500);
        setTimeout("$(\"#jalert_box_cont_"+uid+"\").fadeOut(4000);", 2000);
 
		if(overlay==1){
			$(document).click(function() {
				$("#jalert_overlay_"+uid).fadeOut(100);
				$("#jalert_overlay_"+uid).remove();
			});
		}
	
		$('.msg-btn').click(function() {
			if (overlay==1) {
				$("#jalert_overlay_"+uid).fadeOut(100);
				$("#jalert_overlay_"+uid).remove();
			}
			$("#jalert_box_cont_"+uid).fadeOut(100);
			$("#jalert_box_cont_"+uid).empty();
			$("#jalert_box_cont_"+uid).remove();
			$(window).unbind("resize");
		});
		
		
        //always center
        $(window).resize(function() {alignCenter();});
				
		function alignCenter() {
			var ibox = $("#jalert_box_cont_"+uid);
			var alert_box_width = ibox.width();
			var alert_box_height = ibox.height();
			yOffset = 0;
			if(ibox.css('position')=='absolute'){
				yOffset = document.body.scrollTop;
			}
            /*
			//get the width of the container
            var container_width = tmpobj.innerWidth();
            // get the x position of the container
            var container_left = tmpobj.x();
            //get the center position of the alert box within the container
            var actual_left = ((container_width-alert_box_width)/2)+container_left;
			*/
            //get the y (top) position of the container
            $("#jalert_box_cont_"+uid).css({"margin-left" : "-"+(alert_box_width/2)+"px", 'margin-top' : (yOffset-(alert_box_height/2))+'px'});
			
		}

    };

    //vertical positioning
    $.fn.y = function(n) {
        var result = null;
        this.each(function() {
            var o = this;
            if (n === undefined) {
                var y = 0;
                if (o.offsetParent) {
                    while (o.offsetParent) {
                        y += o.offsetTop;
                        o = o.offsetParent;
                    }
                }
                if (result === null) {
                    result = y;
                } else {
                    result = Math.min(result, y);
                }
            } else {
                o.style.top = n + 'px';
            }
        });
        return result;
    };
    
    //horizontal positioning
    $.fn.x = function(n) {
        var result = null;
        this.each(function() {
            var o = this;
            if (n === undefined) {
                var x = 0;
                if (o.offsetParent) {
                    while (o.offsetParent) {
                        x += o.offsetLeft;
                        o = o.offsetParent;
                    }
                }
                if (result === null) {
                    result = x;
                } else {
                    result = Math.min(result, x);
                }
            } else {
                o.style.left = n + 'px';
            }
        });
        return result;
    };
})(jQuery);
(function($)
{
    var options={};
    var returnHash=[];
    $.fn.RSV=function(params)
    {
        options=$.extend({},$.fn.RSV.defaults,params);
        return this.each(function()
        {
            if(options.extendedArray){
                for(var i=0;i<this.elements.length;++i){
                    var el = this.elements[i];
                    if(el.type == 'checkbox'){
                        var smpName = el.name.replace(/\[[^\]]+]/, '[]');
                        if(smpName != el.name){
                            if(this[smpName] == undefined){
                                this[smpName] = new Array();
                            }
                            this[smpName].push(el);
                        }
                    }
                }
            }
            $(this).bind('submit',{
                currForm:this, 
                options:options
            },$(this).RSV.validate);
            if(options.onlineValidate){
                $(this).find('input, textarea, select')
                .bind('blur',{
                    currForm:this, 
                    options:options
                },$(this).RSV.validate);
            }
        });
    };
    $.fn.RSV.defaults={
        rules:[],
        displayType:"alert-all",
        errorFieldClass:null,
        errorTextIntro:"Please fix the following error(s) and resubmit:",
        errorJSItemBullet:"* ",
        errorHTMLItemBullet:"&bull; ",
        errorTargetElementId:"rsvErrors",
        customErrorHandler:null,
        onCompleteHandler:null,
        onlineValidate:false,
        extendedArray:false
    };
    $.fn.RSV.validate=function(event)
    {
        try{
            options=event.data.options;
            var form=event.data.currForm;
            var rules=options.rules;
            returnHash=[];
            for(var i=0;i<rules.length;i++)
            {
                var row=rules[i].replace(/\\,/ig,"%%C%%");
                row=row.split("#");
                var satisfiesIfConditions=true;
                while(row[0].match("^if:"))
                {
                    var cond=row[0];
                    cond=cond.replace("if:","");
                    var comparison="equal";
                    var parts=[];
                    if(cond.search("!=")!=-1)
                    {
                        parts=cond.split("!=");
                        comparison="not_equal";
                    }
                    else parts=cond.split("=");
                    var fieldToCheck=parts[0];
                    var valueToCheck=parts[1];
                    var fieldnameValue="";
                    if(form[fieldToCheck].type == undefined)
                    {
                        for(var j=0;j<form[fieldToCheck].length;j++)
                        {
                            if(form[fieldToCheck][j].checked)
                                fieldnameValue=form[fieldToCheck][j].value;
                        }
                    }
                    else if(form[fieldToCheck].type == "checkbox")
                    {
                        fieldnameValue=(form[fieldToCheck].checked)?1:0;//form[parts[0]].value;
                    }
                    else
                        fieldnameValue=form[parts[0]].value;//alert(fieldToCheck+'['+fieldnameValue+']'+((fieldnameValue==valueToCheck)?'T':'F')+'('+valueToCheck+')');
                    if(comparison == "equal" && fieldnameValue != valueToCheck)
                    {
                        satisfiesIfConditions=false;
                        break;
                    }
                    else if(comparison == "not_equal" && fieldnameValue == valueToCheck)
                    {
                        satisfiesIfConditions=false;
                        break;
                    }
                    else
                        row.shift();
                }
                if(!satisfiesIfConditions)
                    continue;
                var requirement=row[0];
                var fieldName=row[1];
                var fieldName2,fieldName3,errorMessage,lengthRequirements,date_flag;
                if(requirement!="function"&&form[fieldName]==undefined)
                {
                    alert("RSV Error: the field \""+fieldName+"\" doesn't exist! Please check your form and settings.");
                    return false;
                }
                if(requirement!="function"&&options.errorFieldClass)
                {
                    if(form[fieldName].type==undefined)
                    {
                        for(var j=0;j<form[fieldName].length;j++)
                        {
                            if($(form[fieldName][j]).hasClass(options.errorFieldClass))
                                $(form[fieldName][j]).removeClass(options.errorFieldClass);
                        }
                    }
                    else
                    {
                        if($(form[fieldName]).hasClass(options.errorFieldClass))
                            $(form[fieldName]).removeClass(options.errorFieldClass);
                    }
                }
                if(row.length==6)
                {
                    fieldName2=row[2];
                    fieldName3=row[3];
                    date_flag=row[4];
                    errorMessage=row[5];
                }
                else if(row.length==5)
                {
                    fieldName2=row[2];
                    fieldName3=row[3];
                    errorMessage=row[4];
                }
                else if(row.length==4)
                {
                    fieldName2=row[2];
                    errorMessage=row[3];
                } else errorMessage=row[2];
                if(requirement.match("^length"))
                {
                    lengthRequirements=requirement;
                    requirement="length";
                }
                if(requirement.match("^range"))
                {
                    rangeRequirements=requirement;
                    requirement="range";
                }
                switch(requirement)
                {
                    case"required":
                        if(form[fieldName].type == undefined)
                        {
                            var oneIsChecked=false;
                            for(var j=0;j<form[fieldName].length;j++)
                            {
                                if(form[fieldName][j].checked)
                                    oneIsChecked=true;
                            }
                            if(!oneIsChecked)
                            {
                                if(!processError(form[fieldName],errorMessage))
                                    return false;
                            }
                        }
                        else if(form[fieldName].type == "select-multiple")
                        {
                            var oneIsSelected=false;
                            for(var k=0;k<form[fieldName].length;k++)
                            {
                                if(form[fieldName][k].selected)
                                    oneIsSelected=true;
                            }
                            if(!oneIsSelected || form[fieldName].length==0)
                            {
                                if(!processError(form[fieldName],errorMessage))
                                    return false;
                            }
                        }
                        else if(form[fieldName].type == "checkbox")
                        {
                            if(!form[fieldName].checked)
                            {
                                if(!processError(form[fieldName],errorMessage))
                                    return false;
                            }
                        }
                        else if(!form[fieldName].value)
                        {
                            if(!processError(form[fieldName],errorMessage))
                                return false;
                        }
                        else if((form[fieldName].value == "0") || (form[fieldName].value == "-")) {
                            if(!processError(form[fieldName],errorMessage))
                                return false;
                        }
                        break;
                    case "digits_only":
                        if(form[fieldName].value && form[fieldName].value.match(/\D/))
                        {
                            if(!processError(form[fieldName],errorMessage))
                                return false;
                        }
                        break;
                    case "letters_only":
                        if(form[fieldName].value && form[fieldName].value.match(/[^a-zA-Z]/))
                        {
                            if(!processError(form[fieldName],errorMessage))
                                return false;
                        }
                        break;
                    case "is_alpha":
                        if(form[fieldName].value && form[fieldName].value.match(/\W/))
                        {
                            if(!processError(form[fieldName],errorMessage))
                                return false;
                        }
                        break;
                    case "custom_alpha":
                        var conversion=
                        {
                            "L":"[A-Z]",
                            "V":"[AEIOU]",
                            "l":"[a-z]",
                            "v":"[aeiou]",
                            "D":"[a-zA-Z]",
                            "F":"[aeiouAEIOU]",
                            "C":"[BCDFGHJKLMNPQRSTVWXYZ]",
                            "x":"[0-9]",
                            "c":"[bcdfghjklmnpqrstvwxyz]",
                            "X":"[1-9]",
                            "E":"[bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ]"
                        };
                        var reg_exp_str="";
                        for(var j=0;j<fieldName2.length;j++)
                        {
                            if(conversion[fieldName2.charAt(j)])
                                reg_exp_str += conversion[fieldName2.charAt(j)];
                            else
                                reg_exp_str += fieldName2.charAt(j);
                        }
                        var reg_exp=new RegExp(reg_exp_str);
                        if(form[fieldName].value&&reg_exp.exec(form[fieldName].value)==null)
                        {
                            if(!processError(form[fieldName],errorMessage))
                                return false;
                        }
                        break;
                    case "reg_exp":
                        var reg_exp_str=fieldName2;
                        if(row.length==5)
                            var reg_exp=new RegExp(reg_exp_str,fieldName3.replace('u',''));
                        else
                            var reg_exp=new RegExp(reg_exp_str);
                        if(form[fieldName].value && reg_exp.exec(form[fieldName].value)==null)
                        {
                            if(!processError(form[fieldName],errorMessage))
                                return false;
                        }
                        break;
                    case "length":
                        comparison_rule="";
                        rule_string="";
                        if(lengthRequirements.match(/length=/))
                        {
                            comparison_rule="equal";
                            rule_string=lengthRequirements.replace("length=","");
                        }
                        else if(lengthRequirements.match(/length>=/))
                        {
                            comparison_rule="greater_than_or_equal";
                            rule_string=lengthRequirements.replace("length>=","");
                        }
                        else if(lengthRequirements.match(/length>/))
                        {
                            comparison_rule="greater_than";
                            rule_string=lengthRequirements.replace("length>","");
                        }
                        else if(lengthRequirements.match(/length<=/))
                        {
                            comparison_rule="less_than_or_equal";
                            rule_string=lengthRequirements.replace("length<=","");
                        }
                        else if(lengthRequirements.match(/length</))
                        {
                            comparison_rule="less_than";
                            rule_string=lengthRequirements.replace("length<","");
                        }
                        switch(comparison_rule)
                        {
                            case "greater_than_or_equal":
                                if(!(form[fieldName].value.length>=parseInt(rule_string)))
                                {
                                    if(!processError(form[fieldName],errorMessage))
                                        return false;
                                }
                                break;
                            case "greater_than":
                                if(!(form[fieldName].value.length>parseInt(rule_string)))
                                {
                                    if(!processError(form[fieldName],errorMessage))
                                        return false;
                                }
                                break;
                            case "less_than_or_equal":
                                if(!(form[fieldName].value.length<=parseInt(rule_string)))
                                {
                                    if(!processError(form[fieldName],errorMessage))
                                        return false;
                                }
                                break;
                            case "less_than":
                                if(!(form[fieldName].value.length<parseInt(rule_string)))
                                {
                                    if(!processError(form[fieldName],errorMessage))
                                        return false;
                                }
                                break;
                            case "equal":
                                var range_or_exact_number=rule_string.match(/[^_]+/);
                                var fieldCount=range_or_exact_number[0].split("-");
                                if(fieldCount.length==2)
                                {
                                    if(form[fieldName].value.length<fieldCount[0]||form[fieldName].value.length>fieldCount[1])
                                    {
                                        if(!processError(form[fieldName],errorMessage))
                                            return false;
                                    }
                                }
                                else{
                                    if(form[fieldName].value.length!=fieldCount[0])
                                    {
                                        if(!processError(form[fieldName],errorMessage))
                                            return false;
                                    }
                                }
                                break;
                        }
                        break;
                    case "valid_email":
                        if(form[fieldName].value&&!isValidEmail(form[fieldName].value))
                        {
                            if(!processError(form[fieldName],errorMessage))
                                return false;
                        }
                        break;
                    case "valid_date":
                        var isLaterDate = false;
                        if(date_flag == "later_date")
                            isLaterDate = true;
                        if(!isValidDate(form[fieldName].value,form[fieldName2].value,form[fieldName3].value,isLaterDate))
                        {
                            if(!processError(form[fieldName],errorMessage))
                                return false;
                        }
                        break;
                    case "same_as":
                        if(form[fieldName].value != form[fieldName2].value)
                        {
                            if(!processError(form[fieldName],errorMessage))
                                return false;
                        }
                        break;
                    case "range":
                        comparison_rule="";
                        rule_string="";
                        if(rangeRequirements.match(/range=/))
                        {
                            comparison_rule="equal";
                            rule_string=rangeRequirements.replace("range=","");
                        }
                        else if(rangeRequirements.match(/range>=/))
                        {
                            comparison_rule="greater_than_or_equal";
                            rule_string=rangeRequirements.replace("range>=","");
                        }
                        else if(rangeRequirements.match(/range>/))
                        {
                            comparison_rule="greater_than";
                            rule_string=rangeRequirements.replace("range>","");
                        }
                        else if(rangeRequirements.match(/range<=/))
                        {
                            comparison_rule="less_than_or_equal";
                            rule_string=rangeRequirements.replace("range<=","");
                        }
                        else if(rangeRequirements.match(/range</))
                        {
                            comparison_rule="less_than";
                            rule_string=rangeRequirements.replace("range<","");
                        }
                        switch(comparison_rule)
                        {
                            case "greater_than_or_equal":
                                if(!(form[fieldName].value >= Number(rule_string)))
                                {
                                    if(!processError(form[fieldName],errorMessage))
                                        return false;
                                }
                                break;
                            case "greater_than":
                                if(!(form[fieldName].value > Number(rule_string)))
                                {
                                    if(!processError(form[fieldName],errorMessage))
                                        return false;
                                }
                                break;
                            case "less_than_or_equal":
                                if(!(form[fieldName].value <= Number(rule_string)))
                                {
                                    if(!processError(form[fieldName],errorMessage))
                                        return false;
                                }
                                break;
                            case "less_than":
                                if(!(form[fieldName].value < Number(rule_string)))
                                {
                                    if(!processError(form[fieldName],errorMessage))
                                        return false;
                                }
                                break;
                            case "equal":
                                var rangeValues=rule_string.split("-");
                                if((form[fieldName].value < Number(rangeValues[0])) || (form[fieldName].value > Number(rangeValues[1])))
                                {
                                    if(!processError(form[fieldName],errorMessage))
                                        return false;
                                }
                                break;
                        }
                        break;
                    case "function":
                        custom_function=fieldName;
                        eval("var result = "+custom_function+"()");
                        if(result.constructor.toString().indexOf("Array")!=-1)
                        {
                            for(var j=0;j<result.length;j++)
                            {
                                if(!processError(result[j][0],result[j][1]))
                                    return false;
                            }
                        }
                        break;
                    default:
                        alert("Unknown requirement flag in validateFields(): "+requirement);
                        return false;
                }
            }
            if(typeof options.customErrorHandler=='function')
                return options.customErrorHandler(form,returnHash);
            else if(options.displayType == "alert-all")
            {
                var errorStr=options.errorTextIntro+"\n\n";
                for(var i=0;i<returnHash.length;i++)
                {
                    errorStr+=options.errorJSItemBullet+returnHash[i][1]+"\n";
                    styleField(returnHash[i][0],i==0);
                }
                if(returnHash.length>0)
                {
                    alert(errorStr);
                    return false;
                }
            }
            else if(options.displayType=="display-html")
            {
                var success=displayHTMLErrors(form,returnHash);
                if(!success)
                    return false;
            }
            if(typeof options.onCompleteHandler=='function')
                return options.onCompleteHandler();
            else
                return true;
        }catch(ex){
            return false;
        }
    }
    function processError(obj,message)
    {
        message=message.replace(/%%C%%/ig,",");
        var continueProcessing=true;
        switch(options.displayType)
        {
            case "alert-one":
                alert(message);
                styleField(obj,true);
                continueProcessing=false;
                break;
            case "alert-all":
            case "display-html":
                returnHash.push([obj,message]);
                break;
        }
        return continueProcessing;
    }
    function displayHTMLErrors(f,errorInfo)
    {
        var errorHTML=options.errorTextIntro+"<br /><br />";
        for(var i=0;i<errorInfo.length;i++)
        {
            errorHTML+=options.errorHTMLItemBullet+errorInfo[i][1]+"<br />";
            styleField(errorInfo[i][0],i==0);
        }
        if(errorInfo.length>0)
        {
            $("#"+options.errorTargetElementId).css("display","block");
            $("#"+options.errorTargetElementId).html(errorHTML);
            $.scrollTo("#"+options.errorTargetElementId);
            return false;
        }
        return true;
    }
    function styleField(field,focus)
    {
        focus=false;
        if(field.type==undefined)
        {
            if(focus)
                field[0].focus();
            for(var i=0;i<field.length;i++)
            {
                if(!$(field[i]).hasClass(options.errorFieldClass))
                    $(field[i]).addClass(options.errorFieldClass);
            }
        }
        else
        {
            if(options.errorFieldClass)
                $(field).addClass(options.errorFieldClass);
            if(focus)
                field.focus();
        }
    }
    function isValidEmail(str)
    {
        var s=$.trim(str);
        var at="@";
        var dot=".";
        var lat=s.indexOf(at);
        var lstr=s.length;
        var ldot=s.indexOf(dot);
        if(s.indexOf(at)==-1||(s.indexOf(at)==-1||s.indexOf(at)==0||s.indexOf(at)==lstr)||(s.indexOf(dot)==-1||s.indexOf(dot)==0||s.indexOf(dot)==lstr)||(s.indexOf(at,(lat+1))!=-1)||(s.substring(lat-1,lat)==dot||s.substring(lat+1,lat+2)==dot)||(s.indexOf(dot,(lat+2))==-1)||(s.indexOf(" ")!=-1))
        {
            return false;
        }
        return true;
    }
    function isValidDate(month,day,year,isLaterDate)
    {
        var daysInMonth;
        if((year%4==0)&&((year%100!=0)||(year%400==0)))
            daysInMonth=[31,29,31,30,31,30,31,31,30,31,30,31];
        else
            daysInMonth=[31,28,31,30,31,30,31,31,30,31,30,31];
        if(!month||!day||!year) 
            return false;
        if(1>month||month>12) 
            return false;
        if(year<0) 
            return false;
        if(1>day||day>daysInMonth[month-1]) 
            return false;
        if(isLaterDate){
            var today=new Date();
            var currMonth=today.getMonth()+1;
            var currDay=today.getDate();
            var currYear=today.getFullYear();
            if(String(currMonth).length==1)currMonth="0"+currMonth;
            if(String(currDay).length==1)currDay="0"+currDay;
            var currDate=String(currYear)+String(currMonth)+String(currDay);
            if(String(month).length==1)month="0"+month;
            if(String(day).length==1)day="0"+day;
            incomingDate=String(year)+String(month)+String(day);
            if(Number(currDate)>Number(incomingDate))
                return false;
        }
        return true;
    }
})(jQuery);
/** jQuery textCounting plugin
 * by Brian Swartzfager (http://www.swartzfager.org/blog/jQuery/plugins/textCounting)
 *
 * WILL NEED TO MINIFY FROM THIS ONE
 *
 * This is the documented version of the textCounting plugin, meant to be used as a reference guide for this plugin
 * or for testing purposes.  When you use this plugin in production, you should used the minified version
 * (jquery.textCounting.min.js).
 *
 * --------------------------------------------------------------
 * What Does This Plugin Do
 * --------------------------------------------------------------
 * This plugin will count the number of characters or 'words' (blocks of characters separated by one or more spaces) in
 * a <textarea> every time a character is typed in the <textarea> and display either the number of words or characters in
 * the <textarea> or how many words or characters can still be typed before reaching the set limit.  It can peform this
 * operation on multiple <textarea> elements on a single page.
 *
 * --------------------------------------------------------------
 * Default Behavior
 * --------------------------------------------------------------
 * The default behavior of the plugin is to display the number of characters left before reaching the limit (a character
 * countdown). You can use the plugin for this purpose "as is" (without specifying or changing any settings) if you follow
 * these conventions in your coding:
 *
 * 1.  The <textarea> must have an "id" attribute with a unique value and a "maxLength" attribute with an integer denoting
 * the character limit.
 *
 * 2.  The display element (<p>,<span>,<div>,etc.) where you want the countdown displayed must have an "id" attribute
 * whose value is the combination of the <texarea>'s "id" value and the word "Down".
 *
 *
 * Here's an example of a <textarea> and a <span> element that fit the convention:
 *
 * <textarea id="comments" maxLength="1000" rows="4" cols="60"></textarea>
 * <p>Characters left: <span id="commentsDown"></span></p>
 *
 * Because the element ids and the maxLength value is specific to each <textarea>, you can use a single call of the
 * plugin to display a countdown for all your <textarea> elements:
 *
 * *****************************************
 * <script language="javascript" src="jquery-1.2.3.pack.js"></script>
 * <script language="javascript" src="jquery.textCounting.min.js"></script>
 *
 * <script language="javascript">
 * $(document).ready(function()
 * 		$(":input[type=textarea]").textCounting();
 * });
 * </script>
 * ....
 *
 * <textarea id="justification" maxLength="2000" rows="4" cols="60"></textarea>
 * <p>Characters left: <span id="justificationDown"></span></p>
 *
 * <textarea id="comments" maxLength="1000" rows="4" cols="60"></textarea>
 * <p>Characters left: <span id="commentsDown"></span></p>
 *
 * *****************************************
 *
 * --------------------------------------------------------------
 * Plugin Settings
 * --------------------------------------------------------------
 * Like most jQuery plugins, this plugin contains a number of settings that can be configured in order to change the
 * plugin's behavior.  You can change the settings in one of three ways:
 *
 * 1.  You can denote the settings you want in an object literal and pass that object into the plugin when you invoke it:
 *
 * *****************************************
 * <script language="javascript">
 * var settings= {countWhat: 'words',lengthExceededClass: 'warningClass'};
 * $(":input[type=textarea]").textCounting(settings);
 * </script>
 * *****************************************
 *
 * 2.  You can individually alter each of the 'defaults' properties of the plugin:
 *
 * *****************************************
 * <script language="javascript">
 * $.fn.textCounting.defaults.countWhat = 'words';
 * $.fn.textCounting.defaults.lengthExceededClass = 'warningClass';
 * $(":input[type=textarea]").textCounting(settings);
 * </script>
 * *****************************************
 *
 * 3.  If you also use the Metadata jQuery plugin (http://plugins.jquery.com/project/metadata),
 * you can code the settings in metadata within the "class" attribute of the <textarea>:
 *
 * *****************************************
 * <textarea class="someClass {countWhat:'words',lengthExceededClass:'warningClass'}" name="tBoxOne" id="tBoxOne"...>...
 * *****************************************
 *
 * NOTE:  If you use the metadata method to change any settings, be aware that the changes submitted via the metadata
 * will override any settings set with the first two methods.
 *
 * Here is a list of all of the settings and how they are used:
 *
 * maxLengthSource
 * -----------------------
 * Possible values: "attribute", "list", "metadata"
 * Default value: "attribute"
 *
 * The maxLengthSource setting denotes where the plugin looks for the limit value (the "maxLength") for each <textarea>.
 * The default value is "attribute," meaning that the plugin will look for the attribute in the <textarea> element whose name
 * corresponds to the value of the maxLengthAttribute plugin setting and use its value as the limit value.
 *
 * The problem with defining a custom attribute in the <textarea> element to hold the limit value is that HTML/XHTML
 * validators will cite your web page as being invalid because custom attributes for HTML tags are currently not allowed.
 * If this kind of validity is important to you, you should use the "list" or "metadata" value for maxLengthSource.
 *
 * If maxLengthSource is set to "list", the plugin will use the integer or comma-delimited list of integers in the
 * maxLengthList plugin setting for the limit value (see the notes on the maxLengthList setting for more details).
 *
 * If maxLengthSource is set to "metadata", the plugin assumes that you are using the Metadata jQuery plugin (
 * http://plugins.jquery.com/project/metadata) on the page as well, and the plugin will look for key/attribute in
 * the metadata of the <textarea> (stored in the "class" attribute of the <textarea>) whose name corresponds
 * to the value of the maxLengthAttribute plugin setting and use its value as the limit value.
 *
 * maxLengthList
 * -------------------
 * Possible values: "" (empty), a single integer, or a comma-separated list of intergers (ex. "1000,2500,3000" )
 * Default value: ""
 *
 * If maxLengthSource is set to "list", the plugin will use the integer or comma-delimited list of integers in the
 * maxLengthList plugin setting for the limit value (if maxLengthList is set to "" under these conditions, a JavaScript alert
 * will appear that points out the problem).
 *
 * Make sure you have the same number of integers in the maxLengthList value as you have <textarea> elements
 * affected by the plugin, or the wrong limit value may be associated with the wrong <textarea>
 *
 *
 * maxLengthAttribute
 * -----------------------
 * Possible values: a string denoting an attribute/key name, or "" (if maxLengthSource is set to "list")
 * Default value: "maxLength"
 *
 * The value of the maxLengthAttribute setting denotes the attribute/key where the plugin will look for the character/word
 * limit. If the maxLengthSource setting is set to "attribute" or "metadata" and the maxLengthAttribute is empty, a JavaScript alert
 * will appear that points out the problem.
 *
 * When the maxLengthSource setting is set to "attribute", the plugin will look for the attribute denoted in the value
 * of maxLength attribute within the <textarea> element itself.  When the maxLengthSource setting is set to "metadata",
 * the plugin will look for the attribute denoted in the value of maxLength attribute within the metadata defined in the "class"
 * attribute of the <textarea>.  For example, if maxLengthSource is set to "metadata" and maxLengthAttribute is set to
 * "maxLength", the following example would work:
 *
 * <textarea class="someClass {maxLength:'words'}" name="tBoxOne" id="tBoxOne"...>...
 *
 *
 * countWhat
 * --------------
 * Possible values: "characters", "words"
 * Default value: "characters"
 *
 * The value of countWhat determines if the plugin will count either the number of characters in the <textarea> or the
 * number of 'words' (blocks of characters separated by one or more spaces)
 *
 *
 * countDirection
 * ------------------
 * Possible values: "up","down","up,down" (the order doesn't matter)
 * Default value: "down"
 *
 * The value of countWhat determines if the plugin will calculate and return the current number of characters/words in
 * the <textarea> or if it will return the number of characters/words the user can still type before hitting the set limit.
 * You can also set the plugin to return both values, displaying the result in different elements on the page.
 *
 *
 * targetModifierType
 * ----------------------
 * Possible values: "prefix", "suffix", "id"
 * Default value: "suffix"
 *
 * The "target" in the targetModifierType and targetModifier settings refers to the HTML element where the count value
 * calculated by the plugin will be displayed.  The targetModifierType setting was designed to provide an easy means of
 * associating a particular <textarea> with the HTML element or elements that will display the count value of the <textarea>.
 *
 * If the targetModifierType is set to "suffix", the plugin will display the count value in the HTML element whose "id" attribute
 * value is the combination of the <textarea>'s "id" attribute value with the value of the targetModifier appended to the end
 * of it.  So given the following set of data:
 *
 * <textarea> id:  "comments"
 * targetModifierType: "suffix"
 * targetModifier:  "Countdown"
 *
 * ...the count value calculated by the plugin will be displayed in the text of the HTML element whose "id" attribute is
 * "commentsCountdown"
 *
 * Using the same data but with targetModifierType set to "prefix" instead, the target HTML element would have an id of
 * "Countdowncomments"
 *
 * Using the same data but with targetModifierType set to "id" instead, the plugin will simply look for an HTML element
 * whose id equals the value of the targetModifier setting, so in this example it would simply be "Countdown".
 *
 * You can only set targetModifierType to "id" when there is only 1 <textarea> element on the page or if you plan to
 * define unique targetModifier settings for each separate <textarea> using metadata and the jQuery Metadata plugin:
 * otherwise there is no means of defining unique id values for the multiple count value targets.
 *
 *
 * targetModifier
 * -----------------
 * Possible values: a string or a comma-separated list of strings
 * Default value: "Down"
 *
 * See the explanation of the targetModifierType setting for information on the role of the targetModifier.  If you set the
 * countDirection setting to have the plugin calculate the count values for both "directions" ("up,down"), the targetModifier
 * will also have to be a comma-delimited list denoting where the "up" value should be displayed and where the "down"
 * value should be displayed.
 *
 *
 * lengthExceededClass
 * --------------------------
 * Possible values: a string with the name of a CSS class
 * Default value: "" (empty)
 *
 * If you want to apply a CSS class to the HTML element/elements that display the count value whenever the count value
 * has exceeded the set limit, you can provide the name of that CSS class to the lengthExceededClass setting
 *
 *
 * excludeIds
 * -------------
 * Possible values: a string or comma-delimited list of strings denoting <textarea> ids
 * Default value: "" (empty)
 *
 * The excludeIds setting lets you denote any <textarea> elements you want the plugin to ignore/skip.  The use case for
 * using this setting is when you have multiple <textarea> elements on the page and you want to apply the plugin to most
 * of those <textarea> elements with one or two exceptions.
 *
 * Any <textarea> whose id is listed in the excludeIds setting is completely ignored by the plugin:  the count value is not
 * calculated at all and nothing is displayed.
 *
 *
 * --------------------------------------------------------------
 * Public Functions
 * --------------------------------------------------------------
 * This plugin contains two functions that can be called individually:
 *
 * calculateCount(), with the parameters:
 * 		--obj: a jQuery object representing the <textarea>
 * 		--countWhat:  a string, either "characters" or "words" (not both)
 * 		--direction:  a string, either "up" or "down" (not both)
 * 		--maxCount: an integer, the limit for the characters/words in the <textarea>
 *
 * displayResult(), with the parameters:
 * 		--obj: a jQuery object representing the <textarea>
 * 		--modifierType:  a string, either "id", "suffix", or "prefix"
 * 		--target: a string, the suffix or prefix to be combined with the <textarea>'s id to identify an HTML element
 * 		--textCount: an integer, the current number of characters/words in the <textarea>
 * 		--maxCount: an integer, the limit for the characters/words in the <textarea>
 * 		--direction:  a string, either "up" or "down" (not both)
 * 		--lengthExceededClass: a string, the name of a CSS class to apply to the HTML element defined by the target value
 *
 * Both of these functions can be called in your JavaScript via the plugin, as shown in the example below:
 *
 * <script language="javascript">
 * var tCount= $.fn.textCounting.calculateCount($("#tBoxOne"),'characters','down',150);
 * </script>
 */

(function($) {

    $.fn.textCounting = function(parameters) {

        var opts = $.extend({}, $.fn.textCounting.defaults, parameters);

        if (opts.maxLengthSource== "list")
        {
            if (opts.maxLengthList != "")
            {
                var maxLengthArray= opts.maxLengthList.split(",");
                var lengthsCounter= 0;
            }
            else
            {
                denoteError("The maxLengthSource parameter of the jQuery textCounting plugin was set to 'list', but the maxLengthList parameter is blank.");
                return false;
            }
        }

        return this.each(function() {

            var $box= $(this);

            //Look for the presence of the Metadata plugin and extract any metadata if needed
            var options = $.metadata ? $.extend({}, opts, $box.metadata()) : opts;

            var proceed= true;
            if (options.excludeIds != "")
            {
                proceed= isObjectIncluded($box.attr("id"),options.excludeIds);
            }

            if (proceed)
            {
                switch (options.maxLengthSource)
                {
                    case "list":
                        var maxCount= maxLengthArray[lengthsCounter];
                        lengthsCounter++;
                        break;
                    case "attribute":
                        if (options.maxLengthAttribute != "")
                        {
                            var maxCount= $box.attr(options.maxLengthAttribute);
                        }
                        else
                        {
                            denoteError("The maxLengthSource parameter of the jQuery textCounting plugin was set to 'attribute', but the maxLengthAttribute parameter is blank.");
                            return false;
                        }
                        break;
                    case "metadata":
                        if (options.maxLengthAttribute != "")
                        {
                            var maxCount= $box.metadata()[options.maxLengthAttribute];
                            if(maxCount== undefined)
                            {
                                denoteError("The maxLengthAttribute specified was not found in the metadata of element " + $box.attr("id"));
                                return false;
                            }
                        }
                        else
                        {
                            denoteError("The maxLengthSource parameter of the jQuery textCounting plugin was set to 'metadata', but the maxLengthAttribute parameter is blank.");
                            return false;
                        }
                        break;
                }

                var directionArray= options.countDirection.split(",");
                var targetArray= options.targetModifier.split(",");

                for (var setting=0;setting < directionArray.length;setting++)
                {
                    var currentDirection= directionArray[setting];
                    var textCount= $.fn.textCounting.calculateCount($box,options.countWhat,currentDirection,maxCount);

                    var currentTarget= targetArray[setting];

                    $.fn.textCounting.displayResult($box,options.targetModifierType,currentTarget,textCount,maxCount,currentDirection,options.lengthExceededClass);

                }

                $box.keydown(function (e) {
                    var c = true;
                    for (var setting=0;setting < directionArray.length;setting++)
                    {
                        var currentDirection= directionArray[setting];
                        var textCount= $.fn.textCounting.calculateCount($box,options.countWhat,currentDirection,maxCount);

                        var currentTarget= targetArray[setting];
                        if(textCount<0 || (currentDirection=='down' && textCount==0)) c=false;
                        if(!c && ((e.keyCode==8) || (e.keyCode==16) || ((e.keyCode>=35) && (e.keyCode<=40)) || (e.keyCode==46) || ((e.keyCode>=63232) && (e.keyCode<=63235)))) c = true;
                    }
                    return c;
                });
                $box.keyup(function(){
                    for (var setting=0;setting < directionArray.length;setting++)
                    {
                        var currentDirection= directionArray[setting];
                        var textCount= $.fn.textCounting.calculateCount($box,options.countWhat,currentDirection,maxCount);

                        var currentTarget= targetArray[setting];
                        if(textCount<0) c=false;
                        $.fn.textCounting.displayResult($box,options.targetModifierType,currentTarget,textCount,maxCount,currentDirection,options.lengthExceededClass);
                    }
                });

            } //end of proceed test

        });
    };  //end of main plugin function

    //DEFAULTS
    $.fn.textCounting.defaults = {
        maxLengthSource: "attribute",
        maxLengthList: "",
        maxLengthAttribute: "maxLength",
        countWhat: "characters",
        countDirection: "down",
        targetModifierType: "suffix",
        targetModifier: "Down",
        lengthExceededClass: "",
        excludeIds: ""
    };

    //PUBLIC FUNCTIONS
    $.fn.textCounting.calculateCount = function(obj,countWhat,direction,maxCount) {

        if (countWhat== "characters")
        {
            if (direction== "down")
            {
                var textCount= maxCount-obj.val().length;
            }
            else
            {
                var textCount= obj.val().length;
            }
        }
        else if (countWhat== "words")
        {
            var boxText= 	jQuery.trim(obj.val());
            if(boxText != "")
            {
                var wordArray= boxText.split(/\s+/);
                if (direction== "down")
                {
                    var textCount= maxCount-wordArray.length;
                }
                else
                {
                    var textCount= wordArray.length;
                }
            }
            else
            {
                if (direction== "down")
                {
                    var textCount= maxCount;
                }
                else
                {
                    var textCount= 0;
                }
            }
        }
        return textCount;

    };  //end of $.fn.textCounting.calculateCount function


    $.fn.textCounting.displayResult= function(obj,modifierType,target,textCount,maxCount,direction,lengthExceededClass) {
        switch (modifierType) {
            case "id":
                var $targetElement= $("#" +  target);
                break;
            case "prefix":
                var $targetElement= $("#" +  target + obj.attr("id"));
                break;
            case "suffix":
                var $targetElement= $("#" + obj.attr("id") + target);
                break;
        } //end of switch

        $targetElement.text(textCount);
        if (lengthExceededClass != "")
        {
            if((direction== 'down' && textCount < 0) || (direction== 'up' && textCount > maxCount))
            {
                $targetElement.addClass(lengthExceededClass);
            }
            else
            {
                $targetElement.removeClass(lengthExceededClass);
            }
        }

    };  //end of $.fn.textCounting.displayResult function


    //PRIVATE FUNCTIONS
    function isObjectIncluded(objId,excluded) {
        var outcome= true;
        var exclusionArray= excluded.split(",");
        for (var c= 0;c < exclusionArray.length;c++)
        {
            if (objId== exclusionArray[c])
            {
                outcome= false;
            }
        }
        return outcome;
    }; //end of isObjectIncluded

    function denoteError(msg) {
        if(window.console)
        {
            console.debug(msg);
        }
        else
        {
            alert(msg);
        }
    };

})(jQuery);
/**
 * jQuery.ScrollTo
 * Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 9/11/2008
 *
 * @projectDescription Easy element scrolling using jQuery.
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 * Tested with jQuery 1.2.6. On FF 2/3, IE 6/7, Opera 9.2/5 and Safari 3. on Windows.
 *
 * @author Ariel Flesler
 * @version 1.4
 *
 * @id jQuery.scrollTo
 * @id jQuery.fn.scrollTo
 * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
 *	  The different options for target are:
 *		- A number position (will be applied to all axes).
 *		- A string position ('44', '100px', '+=90', etc ) will be applied to all axes
 *		- A jQuery/DOM element ( logically, child of the element to scroll )
 *		- A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
 *		- A hash { top:x, left:y }, x and y can be any kind of number/string like above.
 * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.
 * @param {Object,Function} settings Optional set of settings or the onAfter callback.
 *	 @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
 *	 @option {Number} duration The OVERALL length of the animation.
 *	 @option {String} easing The easing method for the animation.
 *	 @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
 *	 @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.
 *	 @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.
 *	 @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
 *	 @option {Function} onAfter Function to be called after the scrolling ends.
 *	 @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * @desc Scroll to a fixed position
 * @example $('div').scrollTo( 340 );
 *
 * @desc Scroll relatively to the actual position
 * @example $('div').scrollTo( '+=340px', { axis:'y' } );
 *
 * @dec Scroll using a selector (relative to the scrolled element)
 * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
 *
 * @ Scroll to a DOM element (same for jQuery object)
 * @example var second_child = document.getElementById('container').firstChild.nextSibling;
 *			$('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
 *				alert('scrolled!!');
 *			}});
 *
 * @desc Scroll on both axes, to different values
 * @example $('div').scrollTo( { top: 300, left:'+=200' }, { axis:'xy', offset:-20 } );
 */
;(function( $ ){

	var $scrollTo = $.scrollTo = function( target, duration, settings ){
		$(window).scrollTo( target, duration, settings );
	};

	$scrollTo.defaults = {
		axis:'y',
		duration:1
	};

	// Returns the element that needs to be animated to scroll the window.
	// Kept for backwards compatibility (specially for localScroll & serialScroll)
	$scrollTo.window = function( scope ){
		return $(window).scrollable();
	};

	// Hack, hack, hack... stay away!
	// Returns the real elements to scroll (supports window/iframes, documents and regular nodes)
	$.fn.scrollable = function(){
		return this.map(function(){
			// Just store it, we might need it
			var win = this.parentWindow || this.defaultView,
				// If it's a document, get its iframe or the window if it's THE document
				elem = this.nodeName == '#document' ? win.frameElement || win : this,
				// Get the corresponding document
				doc = elem.contentDocument || (elem.contentWindow || elem).document,
				isWin = elem.setInterval;

			return elem.nodeName == 'IFRAME' || isWin && $.browser.safari ? doc.body
				: isWin ? doc.documentElement
				: this;
		});
	};

	$.fn.scrollTo = function( target, duration, settings ){
		if( typeof duration == 'object' ){
			settings = duration;
			duration = 0;
		}
		if( typeof settings == 'function' )
			settings = { onAfter:settings };

		settings = $.extend( {}, $scrollTo.defaults, settings );
		// Speed is still recognized for backwards compatibility
		duration = duration || settings.speed || settings.duration;
		// Make sure the settings are given right
		settings.queue = settings.queue && settings.axis.length > 1;

		if( settings.queue )
			// Let's keep the overall duration
			duration /= 2;
		settings.offset = both( settings.offset );
		settings.over = both( settings.over );

		return this.scrollable().each(function(){
			var elem = this,
				$elem = $(elem),
				targ = target, toff, attr = {},
				win = $elem.is('html,body');

			switch( typeof targ ){
				// A number will pass the regex
				case 'number':
				case 'string':
					if( /^([+-]=)?\d+(px)?$/.test(targ) ){
						targ = both( targ );
						// We are done
						break;
					}
					// Relative selector, no break!
					targ = $(targ,this);
				case 'object':
					// DOMElement / jQuery
					if( targ.is || targ.style )
						// Get the real position of the target
						toff = (targ = $(targ)).offset();
			}
			$.each( settings.axis.split(''), function( i, axis ){
				var Pos	= axis == 'x' ? 'Left' : 'Top',
					pos = Pos.toLowerCase(),
					key = 'scroll' + Pos,
					old = elem[key],
					Dim = axis == 'x' ? 'Width' : 'Height',
					dim = Dim.toLowerCase();

				if( toff ){// jQuery / DOMElement
					attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );

					// If it's a dom element, reduce the margin
					if( settings.margin ){
						attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;
						attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;
					}

					attr[key] += settings.offset[pos] || 0;

					if( settings.over[pos] )
						// Scroll to a fraction of its width/height
						attr[key] += targ[dim]() * settings.over[pos];
				}else
					attr[key] = targ[pos];

				// Number or 'number'
				if( /^\d+$/.test(attr[key]) )
					// Check the limits
					attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max(Dim) );

				// Queueing axes
				if( !i && settings.queue ){
					// Don't waste time animating, if there's no need.
					if( old != attr[key] )
						// Intermediate animation
						animate( settings.onAfterFirst );
					// Don't animate this axis again in the next iteration.
					delete attr[key];
				}
			});
			animate( settings.onAfter );

			function animate( callback ){
				$elem.animate( attr, duration, settings.easing, callback && function(){
					callback.call(this, target, settings);
				});
			};
			function max( Dim ){
				var attr ='scroll'+Dim,
					doc = elem.ownerDocument;

				return win
						? Math.max( doc.documentElement[attr], doc.body[attr]  )
						: elem[attr];
			};
		}).end();
	};

	function both( val ){
		return typeof val == 'object' ? val : { top:val, left:val };
	};

})( jQuery );
/*
 * FancyBox - jQuery Plugin
 * Simple and fancy lightbox alternative
 *
 * Examples and documentation at: http://fancybox.net
 * 
 * Copyright (c) 2008 - 2010 Janis Skarnelis
 *
 * Version: 1.3.1 (05/03/2010)
 * Requires: jQuery v1.3+
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */
;
(function($) {

	var tmp, loading, overlay, wrap, outer, inner, close, nav_left, nav_right,

		selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [],

		ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i,

		loadingTimer, loadingFrame = 1,

		start_pos, final_pos, busy = false, shadow = 20, fx = $.extend($('<div/>')[0], { prop: 0 }), titleh = 0, 

		isIE6 = !$.support.opacity && !window.XMLHttpRequest,

		/*
		 * Private methods 
		 */

		fancybox_abort = function() {
			loading.hide();

			imgPreloader.onerror = imgPreloader.onload = null;

			if (ajaxLoader) {
				ajaxLoader.abort();
			}

			tmp.empty();
		},

		fancybox_error = function() {
			$.fancybox('<p id="fancybox_error">The requested content cannot be loaded.<br />Please try again later.</p>', {
				'scrolling'		: 'no',
				'padding'		: 20,
				'transitionIn'	: 'none',
				'transitionOut'	: 'none'
			});
		},

		fancybox_get_viewport = function() {
			return [ $(window).width(), $(window).height(), $(document).scrollLeft(), $(document).scrollTop() ];
		},

		fancybox_get_zoom_to = function () {
			var view	= fancybox_get_viewport(),
				to		= {},

				margin = currentOpts.margin,
				resize = currentOpts.autoScale,

				horizontal_space	= (shadow + margin) * 2,
				vertical_space		= (shadow + margin) * 2,
				double_padding		= (currentOpts.padding * 2),
				
				ratio;

			if (currentOpts.width.toString().indexOf('%') > -1) {
				to.width = ((view[0] * parseFloat(currentOpts.width)) / 100) - (shadow * 2) ;
				resize = false;

			} else {
				to.width = currentOpts.width + double_padding;
			}

			if (currentOpts.height.toString().indexOf('%') > -1) {
				to.height = ((view[1] * parseFloat(currentOpts.height)) / 100) - (shadow * 2);
				resize = false;

			} else {
				to.height = currentOpts.height + double_padding;
			}

			if (resize && (to.width > (view[0] - horizontal_space) || to.height > (view[1] - vertical_space))) {
				if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') {
					horizontal_space	+= double_padding;
					vertical_space		+= double_padding;

					ratio = Math.min(Math.min( view[0] - horizontal_space, currentOpts.width) / currentOpts.width, Math.min( view[1] - vertical_space, currentOpts.height) / currentOpts.height);

					to.width	= Math.round(ratio * (to.width	- double_padding)) + double_padding;
					to.height	= Math.round(ratio * (to.height	- double_padding)) + double_padding;

				} else {
					to.width	= Math.min(to.width,	(view[0] - horizontal_space));
					to.height	= Math.min(to.height,	(view[1] - vertical_space));
				}
			}

			to.top	= view[3] + ((view[1] - (to.height	+ (shadow * 2 ))) * 0.5);
			to.left	= view[2] + ((view[0] - (to.width	+ (shadow * 2 ))) * 0.5);

			if (currentOpts.autoScale === false) {
				to.top	= Math.max(view[3] + margin, to.top);
				to.left	= Math.max(view[2] + margin, to.left);
			}

			return to;
		},

		fancybox_format_title = function(title) {
			if (title && title.length) {
				switch (currentOpts.titlePosition) {
					case 'inside':
						return title;
					case 'over':
						return '<span id="fancybox-title-over">' + title + '</span>';
					default:
						return '<span id="fancybox-title-wrap"><span id="fancybox-title-left"></span><span id="fancybox-title-main">' + title + '</span><span id="fancybox-title-right"></span></span>';
				}
			}

			return false;
		},

		fancybox_process_title = function() {
			var title	= currentOpts.title,
				width	= final_pos.width - (currentOpts.padding * 2),
				titlec	= 'fancybox-title-' + currentOpts.titlePosition;
				
			$('#fancybox-title').remove();

			titleh = 0;

			if (currentOpts.titleShow === false) {
				return;
			}

			title = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(title, currentArray, currentIndex, currentOpts) : fancybox_format_title(title);

			if (!title || title === '') {
				return;
			}

			$('<div id="fancybox-title" class="' + titlec + '" />').css({
				'width'			: width,
				'paddingLeft'	: currentOpts.padding,
				'paddingRight'	: currentOpts.padding
			}).html(title).appendTo('body');

			switch (currentOpts.titlePosition) {
				case 'inside':
					titleh = $("#fancybox-title").outerHeight(true) - currentOpts.padding;
					final_pos.height += titleh;
				break;

				case 'over':
					$('#fancybox-title').css('bottom', currentOpts.padding);
				break;

				default:
					$('#fancybox-title').css('bottom', $("#fancybox-title").outerHeight(true) * -1);
				break;
			}

			$('#fancybox-title').appendTo( outer ).hide();
		},

		fancybox_set_navigation = function() {
			$(document).unbind('keydown.fb').bind('keydown.fb', function(e) {
				if (e.keyCode == 27 && currentOpts.enableEscapeButton) {
					e.preventDefault();
					$.fancybox.close();

				} else if (e.keyCode == 37) {
					e.preventDefault();
					$.fancybox.prev();

				} else if (e.keyCode == 39) {
					e.preventDefault();
					$.fancybox.next();
				}
			});

			if ($.fn.mousewheel) {
				wrap.unbind('mousewheel.fb');

				if (currentArray.length > 1) {
					wrap.bind('mousewheel.fb', function(e, delta) {
						e.preventDefault();

						if (busy || delta === 0) {
							return;
						}

						if (delta > 0) {
							$.fancybox.prev();
						} else {
							$.fancybox.next();
						}
					});
				}
			}

			if (!currentOpts.showNavArrows) { return; }

			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) {
				nav_left.show();
			}

			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) {
				nav_right.show();
			}
		},

		fancybox_preload_images = function() {
			var href, 
				objNext;
				
			if ((currentArray.length -1) > currentIndex) {
				href = currentArray[ currentIndex + 1 ].href;

				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
					objNext = new Image();
					objNext.src = href;
				}
			}

			if (currentIndex > 0) {
				href = currentArray[ currentIndex - 1 ].href;

				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
					objNext = new Image();
					objNext.src = href;
				}
			}
		},

		_finish = function () {
			inner.css('overflow', (currentOpts.scrolling == 'auto' ? (currentOpts.type == 'image' || currentOpts.type == 'iframe' || currentOpts.type == 'swf' ? 'hidden' : 'auto') : (currentOpts.scrolling == 'yes' ? 'auto' : 'visible')));

			if (!$.support.opacity) {
				inner.get(0).style.removeAttribute('filter');
				wrap.get(0).style.removeAttribute('filter');
			}

			$('#fancybox-title').show();

			if (currentOpts.hideOnContentClick)	{
				inner.one('click', $.fancybox.close);
			}
			if (currentOpts.hideOnOverlayClick)	{
				overlay.one('click', $.fancybox.close);
			}

			if (currentOpts.showCloseButton) {
				close.show();
			}

			fancybox_set_navigation();

			$(window).bind("resize.fb", $.fancybox.center);

			if (currentOpts.centerOnScroll) {
				$(window).bind("scroll.fb", $.fancybox.center);
			} else {
				$(window).unbind("scroll.fb");
			}

			if ($.isFunction(currentOpts.onComplete)) {
				currentOpts.onComplete(currentArray, currentIndex, currentOpts);
			}

			busy = false;

			fancybox_preload_images();
		},

		fancybox_draw = function(pos) {
			var width	= Math.round(start_pos.width	+ (final_pos.width	- start_pos.width)	* pos),
				height	= Math.round(start_pos.height	+ (final_pos.height	- start_pos.height)	* pos),

				top		= Math.round(start_pos.top	+ (final_pos.top	- start_pos.top)	* pos),
				left	= Math.round(start_pos.left	+ (final_pos.left	- start_pos.left)	* pos);

			wrap.css({
				'width'		: width		+ 'px',
				'height'	: height	+ 'px',
				'top'		: top		+ 'px',
				'left'		: left		+ 'px'
			});

			width	= Math.max(width - currentOpts.padding * 2, 0);
			height	= Math.max(height - (currentOpts.padding * 2 + (titleh * pos)), 0);

			inner.css({
				'width'		: width		+ 'px',
				'height'	: height	+ 'px'
			});

			if (typeof final_pos.opacity !== 'undefined') {
				wrap.css('opacity', (pos < 0.5 ? 0.5 : pos));
			}
		},

		fancybox_get_obj_pos = function(obj) {
			var pos		= obj.offset();

			pos.top		+= parseFloat( obj.css('paddingTop') )	|| 0;
			pos.left	+= parseFloat( obj.css('paddingLeft') )	|| 0;

			pos.top		+= parseFloat( obj.css('border-top-width') )	|| 0;
			pos.left	+= parseFloat( obj.css('border-left-width') )	|| 0;

			pos.width	= obj.width();
			pos.height	= obj.height();

			return pos;
		},

		fancybox_get_zoom_from = function() {
			var orig = selectedOpts.orig ? $(selectedOpts.orig) : false,
				from = {},
				pos,
				view;

			if (orig && orig.length) {
				pos = fancybox_get_obj_pos(orig);

				from = {
					width	: (pos.width	+ (currentOpts.padding * 2)),
					height	: (pos.height	+ (currentOpts.padding * 2)),
					top		: (pos.top		- currentOpts.padding - shadow),
					left	: (pos.left		- currentOpts.padding - shadow)
				};
				
			} else {
				view = fancybox_get_viewport();

				from = {
					width	: 1,
					height	: 1,
					top		: view[3] + view[1] * 0.5,
					left	: view[2] + view[0] * 0.5
				};
			}

			return from;
		},

		fancybox_show = function() {
			loading.hide();

			if (wrap.is(":visible") && $.isFunction(currentOpts.onCleanup)) {
				if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) {
					$.event.trigger('fancybox-cancel');

					busy = false;
					return;
				}
			}

			currentArray	= selectedArray;
			currentIndex	= selectedIndex;
			currentOpts		= selectedOpts;

			inner.get(0).scrollTop	= 0;
			inner.get(0).scrollLeft	= 0;

			if (currentOpts.overlayShow) {
				if (isIE6) {
					$('select:not(#fancybox-tmp select)').filter(function() {
						return this.style.visibility !== 'hidden';
					}).css({'visibility':'hidden'}).one('fancybox-cleanup', function() {
						this.style.visibility = 'inherit';
					});
				}

				overlay.css({
					'background-color'	: currentOpts.overlayColor,
					'opacity'			: currentOpts.overlayOpacity
				}).unbind().show();
			}

			final_pos = fancybox_get_zoom_to();

			fancybox_process_title();

			if (wrap.is(":visible")) {
				$( close.add( nav_left ).add( nav_right ) ).hide();

				var pos = wrap.position(),
					equal;

				start_pos = {
					top		:	pos.top ,
					left	:	pos.left,
					width	:	wrap.width(),
					height	:	wrap.height()
				};

				equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height);

				inner.fadeOut(currentOpts.changeFade, function() {
					var finish_resizing = function() {
						inner.html( tmp.contents() ).fadeIn(currentOpts.changeFade, _finish);
					};
					
					$.event.trigger('fancybox-change');

					inner.empty().css('overflow', 'hidden');

					if (equal) {
						inner.css({
							top			: currentOpts.padding,
							left		: currentOpts.padding,
							width		: Math.max(final_pos.width	- (currentOpts.padding * 2), 1),
							height		: Math.max(final_pos.height	- (currentOpts.padding * 2) - titleh, 1)
						});
						
						finish_resizing();

					} else {
						inner.css({
							top			: currentOpts.padding,
							left		: currentOpts.padding,
							width		: Math.max(start_pos.width	- (currentOpts.padding * 2), 1),
							height		: Math.max(start_pos.height	- (currentOpts.padding * 2), 1)
						});
						
						fx.prop = 0;

						$(fx).animate({ prop: 1 }, {
							 duration	: currentOpts.changeSpeed,
							 easing		: currentOpts.easingChange,
							 step		: fancybox_draw,
							 complete	: finish_resizing
						});
					}
				});

				return;
			}

			wrap.css('opacity', 1);

			if (currentOpts.transitionIn == 'elastic') {
				start_pos = fancybox_get_zoom_from();

				inner.css({
						top			: currentOpts.padding,
						left		: currentOpts.padding,
						width		: Math.max(start_pos.width	- (currentOpts.padding * 2), 1),
						height		: Math.max(start_pos.height	- (currentOpts.padding * 2), 1)
					})
					.html( tmp.contents() );

				wrap.css(start_pos).show();

				if (currentOpts.opacity) {
					final_pos.opacity = 0;
				}

				fx.prop = 0;

				$(fx).animate({ prop: 1 }, {
					 duration	: currentOpts.speedIn,
					 easing		: currentOpts.easingIn,
					 step		: fancybox_draw,
					 complete	: _finish
				});

			} else {
				inner.css({
						top			: currentOpts.padding,
						left		: currentOpts.padding,
						width		: Math.max(final_pos.width	- (currentOpts.padding * 2), 1),
						height		: Math.max(final_pos.height	- (currentOpts.padding * 2) - titleh, 1)
					})
					.html( tmp.contents() );

				wrap.css( final_pos ).fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish );
			}
		},

		fancybox_process_inline = function() {
			tmp.width(	selectedOpts.width );
			tmp.height(	selectedOpts.height );

			if (selectedOpts.width	== 'auto') {
				selectedOpts.width = tmp.width();
			}
			if (selectedOpts.height	== 'auto') {
				selectedOpts.height	= tmp.height();
			}

			fancybox_show();
		},
		
		fancybox_process_image = function() {
			busy = true;

			selectedOpts.width	= imgPreloader.width;
			selectedOpts.height	= imgPreloader.height;

			$("<img />").attr({
				'id'	: 'fancybox-img',
				'src'	: imgPreloader.src,
				'alt'	: selectedOpts.title
			}).appendTo( tmp );

			fancybox_show();
		},

		fancybox_start = function() {
			fancybox_abort();

			var obj	= selectedArray[ selectedIndex ],
				href, 
				type, 
				title,
				str,
				emb,
				selector,
				data;

			selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox')));
			title = obj.title || $(obj).title || selectedOpts.title || '';
			
			if (obj.nodeName && !selectedOpts.orig) {
				selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj);
			}

			if (title === '' && selectedOpts.orig) {
				title = selectedOpts.orig.attr('alt');
			}

			if (obj.nodeName && (/^(?:javascript|#)/i).test(obj.href)) {
				href = selectedOpts.href || null;
			} else {
				href = selectedOpts.href || obj.href || null;
			}

			if (selectedOpts.type) {
				type = selectedOpts.type;

				if (!href) {
					href = selectedOpts.content;
				}
				
			} else if (selectedOpts.content) {
				type	= 'html';

			} else if (href) {
				if (href.match(imgRegExp)) {
					type = 'image';

				} else if (href.match(swfRegExp)) {
					type = 'swf';

				} else if ($(obj).hasClass("iframe")) {
					type = 'iframe';

				} else if (href.match(/#/)) {
					obj = href.substr(href.indexOf("#"));

					type = $(obj).length > 0 ? 'inline' : 'ajax';
				} else {
					type = 'ajax';
				}
			} else {
				type = 'inline';
			}

			selectedOpts.type	= type;
			selectedOpts.href	= href;
			selectedOpts.title	= title;

			if (selectedOpts.autoDimensions && selectedOpts.type !== 'iframe' && selectedOpts.type !== 'swf') {
				selectedOpts.width		= 'auto';
				selectedOpts.height		= 'auto';
			}

			if (selectedOpts.modal) {
				selectedOpts.overlayShow		= true;
				selectedOpts.hideOnOverlayClick	= false;
				selectedOpts.hideOnContentClick	= false;
				selectedOpts.enableEscapeButton	= false;
				selectedOpts.showCloseButton	= false;
			}

			if ($.isFunction(selectedOpts.onStart)) {
				if (selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts) === false) {
					busy = false;
					return;
				}
			}

			tmp.css('padding', (shadow + selectedOpts.padding + selectedOpts.margin));

			$('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() {
				$(this).replaceWith(inner.children());
			});

			switch (type) {
				case 'html' :
					tmp.html( selectedOpts.content );
					fancybox_process_inline();
				break;

				case 'inline' :
					$('<div class="fancybox-inline-tmp" />').hide().insertBefore( $(obj) ).bind('fancybox-cleanup', function() {
						$(this).replaceWith(inner.children());
					}).bind('fancybox-cancel', function() {
						$(this).replaceWith(tmp.children());
					});

					$(obj).appendTo(tmp);

					fancybox_process_inline();
				break;

				case 'image':
					busy = false;

					$.fancybox.showActivity();

					imgPreloader = new Image();

					imgPreloader.onerror = function() {
						fancybox_error();
					};

					imgPreloader.onload = function() {
						imgPreloader.onerror = null;
						imgPreloader.onload = null;
						fancybox_process_image();
					};

					imgPreloader.src = href;
		
				break;

				case 'swf':
					str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>';
					emb = '';
					
					$.each(selectedOpts.swf, function(name, val) {
						str += '<param name="' + name + '" value="' + val + '"></param>';
						emb += ' ' + name + '="' + val + '"';
					});

					str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>';

					tmp.html(str);

					fancybox_process_inline();
				break;

				case 'ajax':
					selector	= href.split('#', 2);
					data		= selectedOpts.ajax.data || {};

					if (selector.length > 1) {
						href = selector[0];

						if (typeof data == "string") {
							data += '&selector=' + selector[1];
						} else {
							data.selector = selector[1];
						}
					}

					busy = false;
					$.fancybox.showActivity();

					ajaxLoader = $.ajax($.extend(selectedOpts.ajax, {
						url		: href,
						data	: data,
						error	: fancybox_error,
						success : function(data, textStatus, XMLHttpRequest) {
							if (ajaxLoader.status == 200) {
								tmp.html( data );
								fancybox_process_inline();
							}
						}
					}));

				break;

				case 'iframe' :
					$('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" scrolling="' + selectedOpts.scrolling + '" src="' + selectedOpts.href + '"></iframe>').appendTo(tmp);
					fancybox_show();
				break;
			}
		},

		fancybox_animate_loading = function() {
			if (!loading.is(':visible')){
				clearInterval(loadingTimer);
				return;
			}

			$('div', loading).css('top', (loadingFrame * -40) + 'px');

			loadingFrame = (loadingFrame + 1) % 12;
		},

		fancybox_init = function() {
			if ($("#fancybox-wrap").length) {
				return;
			}

			$('body').append(
				tmp			= $('<div id="fancybox-tmp"></div>'),
				loading		= $('<div id="fancybox-loading"><div></div></div>'),
				overlay		= $('<div id="fancybox-overlay"></div>'),
				wrap		= $('<div id="fancybox-wrap"></div>')
			);

			if (!$.support.opacity) {
				wrap.addClass('fancybox-ie');
				loading.addClass('fancybox-ie');
			}

			outer = $('<div id="fancybox-outer"></div>')
				.append('<div class="fancy-bg" id="fancy-bg-n"></div><div class="fancy-bg" id="fancy-bg-ne"></div><div class="fancy-bg" id="fancy-bg-e"></div><div class="fancy-bg" id="fancy-bg-se"></div><div class="fancy-bg" id="fancy-bg-s"></div><div class="fancy-bg" id="fancy-bg-sw"></div><div class="fancy-bg" id="fancy-bg-w"></div><div class="fancy-bg" id="fancy-bg-nw"></div>')
				.appendTo( wrap );

			outer.append(
				inner		= $('<div id="fancybox-inner"></div>'),
				close		= $('<a id="fancybox-close"></a>'),

				nav_left	= $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),
				nav_right	= $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>')
			);

			close.click($.fancybox.close);
			loading.click($.fancybox.cancel);

			nav_left.click(function(e) {
				e.preventDefault();
				$.fancybox.prev();
			});

			nav_right.click(function(e) {
				e.preventDefault();
				$.fancybox.next();
			});

			if (isIE6) {
				overlay.get(0).style.setExpression('height',	"document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'");
				loading.get(0).style.setExpression('top',		"(-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px'");

				outer.prepend('<iframe id="fancybox-hide-sel-frame" src="javascript:\'\';" scrolling="no" frameborder="0" ></iframe>');
			}
		};

	/*
	 * Public methods 
	 */

	$.fn.fancybox = function(options) {
		$(this)
			.data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {})))
			.unbind('click.fb').bind('click.fb', function(e) {
				e.preventDefault();

				if (busy) {
					return;
				}

				busy = true;

				$(this).blur();

				selectedArray	= [];
				selectedIndex	= 0;

				var rel = $(this).attr('rel') || '';

				if (!rel || rel == '' || rel === 'nofollow') {
					selectedArray.push(this);

				} else {
					selectedArray	= $("a[rel=" + rel + "], area[rel=" + rel + "]");
					selectedIndex	= selectedArray.index( this );
				}

				fancybox_start();

				return false;
			});

		return this;
	};

	$.fancybox = function(obj) {
		if (busy) {
			return;
		}

		busy = true;

		var opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {};

		selectedArray	= [];
		selectedIndex	= opts.index || 0;

		if ($.isArray(obj)) {
			for (var i = 0, j = obj.length; i < j; i++) {
				if (typeof obj[i] == 'object') {
					$(obj[i]).data('fancybox', $.extend({}, opts, obj[i]));
				} else {
					obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts));
				}
			}

			selectedArray = jQuery.merge(selectedArray, obj);

		} else {
			if (typeof obj == 'object') {
				$(obj).data('fancybox', $.extend({}, opts, obj));
			} else {
				obj = $({}).data('fancybox', $.extend({content : obj}, opts));
			}

			selectedArray.push(obj);
		}

		if (selectedIndex > selectedArray.length || selectedIndex < 0) {
			selectedIndex = 0;
		}

		fancybox_start();
	};

	$.fancybox.showActivity = function() {
		clearInterval(loadingTimer);

		loading.show();
		loadingTimer = setInterval(fancybox_animate_loading, 66);
	};

	$.fancybox.hideActivity = function() {
		loading.hide();
	};

	$.fancybox.next = function() {
		return $.fancybox.pos( currentIndex + 1);
	};
	
	$.fancybox.prev = function() {
		return $.fancybox.pos( currentIndex - 1);
	};

	$.fancybox.pos = function(pos) {
		if (busy) {
			return;
		}

		pos = parseInt(pos, 10);

		if (pos > -1 && currentArray.length > pos) {
			selectedIndex = pos;
			fancybox_start();
		}

		if (currentOpts.cyclic && currentArray.length > 1 && pos < 0) {
			selectedIndex = currentArray.length - 1;
			fancybox_start();
		}

		if (currentOpts.cyclic && currentArray.length > 1 && pos >= currentArray.length) {
			selectedIndex = 0;
			fancybox_start();
		}

		return;
	};

	$.fancybox.cancel = function() {
		if (busy) {
			return;
		}

		busy = true;

		$.event.trigger('fancybox-cancel');

		fancybox_abort();

		if (selectedOpts && $.isFunction(selectedOpts.onCancel)) {
			selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts);
		}

		busy = false;
	};

	// Note: within an iframe use - parent.$.fancybox.close();
	$.fancybox.close = function() {
		if (busy || wrap.is(':hidden')) {
			return;
		}

		busy = true;

		if (currentOpts && $.isFunction(currentOpts.onCleanup)) {
			if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) {
				busy = false;
				return;
			}
		}

		fancybox_abort();

		$(close.add( nav_left ).add( nav_right )).hide();

		$('#fancybox-title').remove();

		wrap.add(inner).add(overlay).unbind();

		$(window).unbind("resize.fb scroll.fb");
		$(document).unbind('keydown.fb');

		function _cleanup() {
			overlay.fadeOut('fast');

			wrap.hide();

			$.event.trigger('fancybox-cleanup');

			inner.empty();

			if ($.isFunction(currentOpts.onClosed)) {
				currentOpts.onClosed(currentArray, currentIndex, currentOpts);
			}

			currentArray	= selectedOpts	= [];
			currentIndex	= selectedIndex	= 0;
			currentOpts		= selectedOpts	= {};

			busy = false;
		}

		inner.css('overflow', 'hidden');

		if (currentOpts.transitionOut == 'elastic') {
			start_pos = fancybox_get_zoom_from();

			var pos = wrap.position();

			final_pos = {
				top		:	pos.top ,
				left	:	pos.left,
				width	:	wrap.width(),
				height	:	wrap.height()
			};

			if (currentOpts.opacity) {
				final_pos.opacity = 1;
			}

			fx.prop = 1;

			$(fx).animate({ prop: 0 }, {
				 duration	: currentOpts.speedOut,
				 easing		: currentOpts.easingOut,
				 step		: fancybox_draw,
				 complete	: _cleanup
			});

		} else {
			wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup);
		}
	};

	$.fancybox.resize = function() {
		var c, h;
		
		if (busy || wrap.is(':hidden')) {
			return;
		}

		busy = true;

		c = inner.wrapInner("<div style='overflow:auto'></div>").children();
		h = c.height();

		wrap.css({height:	h + (currentOpts.padding * 2) + titleh});
		inner.css({height:	h});

		c.replaceWith(c.children());

		$.fancybox.center();
	};

	$.fancybox.center = function() {
		busy = true;

		var view	= fancybox_get_viewport(),
			margin	= currentOpts.margin,
			to		= {};

		to.top	= view[3] + ((view[1] - ((wrap.height() - titleh) + (shadow * 2 ))) * 0.5);
		to.left	= view[2] + ((view[0] - (wrap.width() + (shadow * 2 ))) * 0.5);

		to.top	= Math.max(view[3] + margin, to.top);
		to.left	= Math.max(view[2] + margin, to.left);

		wrap.css(to);

		busy = false;
	};

	$.fn.fancybox.defaults = {
		padding				:	10,
		margin				:	20,
		opacity				:	false,
		modal				:	false,
		cyclic				:	false,
		scrolling			:	'auto',	// 'auto', 'yes' or 'no'

		width				:	560,
		height				:	340,

		autoScale			:	true,
		autoDimensions		:	true,
		centerOnScroll		:	false,

		ajax				:	{},
		swf					:	{ wmode: 'transparent' },

		hideOnOverlayClick	:	true,
		hideOnContentClick	:	false,

		overlayShow			:	true,
		overlayOpacity		:	0.3,
		overlayColor		:	'#666',

		titleShow			:	true,
		titlePosition		:	'outside',	// 'outside', 'inside' or 'over'
		titleFormat			:	null,

		transitionIn		:	'fade',	// 'elastic', 'fade' or 'none'
		transitionOut		:	'fade',	// 'elastic', 'fade' or 'none'

		speedIn				:	300,
		speedOut			:	300,

		changeSpeed			:	300,
		changeFade			:	'fast',

		easingIn			:	'swing',
		easingOut			:	'swing',

		showCloseButton		:	true,
		showNavArrows		:	true,
		enableEscapeButton	:	true,

		onStart				:	null,
		onCancel			:	null,
		onComplete			:	null,
		onCleanup			:	null,
		onClosed			:	null
	};

	$(document).ready(function() {
		fancybox_init();
	});

})(jQuery);
;/*
 * Metadata - jQuery plugin for parsing metadata from elements
 *
 * Copyright (c) 2006 John Resig, Yehuda Katz, J�Ürn Zaefferer, Paul McLanahan
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.metadata.js 3640 2007-10-11 18:34:38Z pmclanahan $
 *
 */

/**
 * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
 * in the JSON will become a property of the element itself.
 *
 * There are three supported types of metadata storage:
 *
 *   attr:  Inside an attribute. The name parameter indicates *which* attribute.
 *          
 *   class: Inside the class attribute, wrapped in curly braces: { }
 *   
 *   elem:  Inside a child element (e.g. a script tag). The
 *          name parameter indicates *which* element.
 *          
 * The metadata for an element is loaded the first time the element is accessed via jQuery.
 *
 * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
 * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
 * 
 * @name $.metadata.setType
 *
 * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("class")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from the class attribute
 * 
 * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("attr", "data")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a "data" attribute
 * 
 * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
 * @before $.metadata.setType("elem", "script")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a nested script element
 * 
 * @param String type The encoding type
 * @param String name The name of the attribute to be used to get metadata (optional)
 * @cat Plugins/Metadata
 * @descr Sets the type of encoding to be used when loading metadata for the first time
 * @type undefined
 * @see metadata()
 */

(function($) {

$.extend({
	metadata : {
		defaults : {
			type: 'class',
			name: 'metadata',
			cre: /({.*})/,
			single: 'metadata'
		},
		setType: function( type, name ){
			this.defaults.type = type;
			this.defaults.name = name;
		},
		get: function( elem, opts ){
			var settings = $.extend({},this.defaults,opts);
			// check for empty string in single property
			if ( !settings.single.length ) settings.single = 'metadata';
			
			var data = $.data(elem, settings.single);
			// returned cached data if it already exists
			if ( data ) return data;
			
			data = "{}";
			
			if ( settings.type == "class" ) {
				var m = settings.cre.exec( elem.className );
				if ( m )
					data = m[1];
			} else if ( settings.type == "elem" ) {
				if( !elem.getElementsByTagName ) return;
				var e = elem.getElementsByTagName(settings.name);
				if ( e.length )
					data = $.trim(e[0].innerHTML);
			} else if ( elem.getAttribute != undefined ) {
				var attr = elem.getAttribute( settings.name );
				if ( attr )
					data = attr;
			}
			
			if ( data.indexOf( '{' ) <0 )
			data = "{" + data + "}";
			
			data = eval("(" + data + ")");
			
			$.data( elem, settings.single, data );
			return data;
		}
	}
});

/**
 * Returns the metadata object for the first member of the jQuery object.
 *
 * @name metadata
 * @descr Returns element's metadata object
 * @param Object opts An object contianing settings to override the defaults
 * @type jQuery
 * @cat Plugins/Metadata
 */
$.fn.metadata = function( opts ){
	return $.metadata.get( this[0], opts );
};

})(jQuery);/**
 * --------------------------------------------------------------------
 * jQuery-Plugin "pngFix"
 * Version: 1.1, 11.09.2007
 * by Andreas Eberhard, andreas.eberhard@gmail.com
 *                      http://jquery.andreaseberhard.de/
 *
 * Copyright (c) 2007 Andreas Eberhard
 * Licensed under GPL (http://www.opensource.org/licenses/gpl-license.php)
 *
 * Changelog:
 *    11.09.2007 Version 1.1
 *    - removed noConflict
 *    - added png-support for input type=image
 *    - 01.08.2007 CSS background-image support extension added by Scott Jehl, scott@filamentgroup.com, http://www.filamentgroup.com
 *    31.05.2007 initial Version 1.0
 * --------------------------------------------------------------------
 * @example $(function(){$(document).pngFix();});
 * @desc Fixes all PNG's in the document on document.ready
 *
 * jQuery(function(){jQuery(document).pngFix();});
 * @desc Fixes all PNG's in the document on document.ready when using noConflict
 *
 * @example $(function(){$('div.examples').pngFix();});
 * @desc Fixes all PNG's within div with class examples
 *
 * @example $(function(){$('div.examples').pngFix( { blankgif:'ext.gif' } );});
 * @desc Fixes all PNG's within div with class examples, provides blank gif for input with png
 * --------------------------------------------------------------------
 */

(function($) {

jQuery.fn.pngFix = function(settings) {

	// Settings
	settings = jQuery.extend({
		blankgif: 'blank.gif'
	}, settings);

	var ie55 = (navigator.appName == "Microsoft Internet Explorer" && parseInt(navigator.appVersion) == 4 && navigator.appVersion.indexOf("MSIE 5.5") != -1);
	var ie6 = (navigator.appName == "Microsoft Internet Explorer" && parseInt(navigator.appVersion) == 4 && navigator.appVersion.indexOf("MSIE 6.0") != -1);

	if (jQuery.browser.msie && (ie55 || ie6)) {

		//fix images with png-source
		jQuery(this).find("img[@src$=.png]").each(function() {

			jQuery(this).attr('width',jQuery(this).width());
			jQuery(this).attr('height',jQuery(this).height());

			var prevStyle = '';
			var strNewHTML = '';
			var imgId = (jQuery(this).attr('id')) ? 'id="' + jQuery(this).attr('id') + '" ' : '';
			var imgClass = (jQuery(this).attr('class')) ? 'class="' + jQuery(this).attr('class') + '" ' : '';
			var imgTitle = (jQuery(this).attr('title')) ? 'title="' + jQuery(this).attr('title') + '" ' : '';
			var imgAlt = (jQuery(this).attr('alt')) ? 'alt="' + jQuery(this).attr('alt') + '" ' : '';
			var imgAlign = (jQuery(this).attr('align')) ? 'float:' + jQuery(this).attr('align') + ';' : '';
			var imgHand = (jQuery(this).parent().attr('href')) ? 'cursor:hand;' : '';
			if (this.style.border) {
				prevStyle += 'border:'+this.style.border+';';
				this.style.border = '';
			}
			if (this.style.padding) {
				prevStyle += 'padding:'+this.style.padding+';';
				this.style.padding = '';
			}
			if (this.style.margin) {
				prevStyle += 'margin:'+this.style.margin+';';
				this.style.margin = '';
			}
			var imgStyle = (this.style.cssText);

			strNewHTML += '<span '+imgId+imgClass+imgTitle+imgAlt;
			strNewHTML += 'style="position:relative;white-space:pre-line;display:inline-block;background:transparent;'+imgAlign+imgHand;
			strNewHTML += 'width:' + jQuery(this).width() + 'px;' + 'height:' + jQuery(this).height() + 'px;';
			strNewHTML += 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader' + '(src=\'' + jQuery(this).attr('src') + '\', sizingMethod=\'scale\');';
			strNewHTML += imgStyle+'"></span>';
			if (prevStyle != ''){
				strNewHTML = '<span style="position:relative;display:inline-block;'+prevStyle+imgHand+'width:' + jQuery(this).width() + 'px;' + 'height:' + jQuery(this).height() + 'px;'+'">' + strNewHTML + '</span>';
			}

			jQuery(this).hide();
			jQuery(this).after(strNewHTML);

		});

		// fix css background pngs
		jQuery(this).find("*").each(function(){
			var bgIMG = jQuery(this).css('background-image');
			if(bgIMG.indexOf(".png")!=-1){
				var iebg = bgIMG.split('url("')[1].split('")')[0];
				jQuery(this).css('background-image', 'none');
				jQuery(this).get(0).runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + iebg + "',sizingMethod='scale')";
			}
		});
		
		//fix input with png-source
		jQuery(this).find("input[@src$=.png]").each(function() {
			var bgIMG = jQuery(this).attr('src');
			jQuery(this).get(0).runtimeStyle.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader' + '(src=\'' + bgIMG + '\', sizingMethod=\'scale\');';
   		jQuery(this).attr('src', settings.blankgif)
		});
	
	}
	
	return jQuery;

};

})(jQuery);
/**
 * jQuery Plugin colorBlend v1.6.0
 * Requires jQuery 1.2.6+ (Not tested with earlier versions).
 * Based on the Fade plugin http://plugins.jquery.com/project/fade
 * Code losely based on the Cycle plugin http://plugins.jquery.com/project/cycle It was a great resource in creating this one)
 * Copyright (c) 2007-2008 Aaron E. [jquery at happinessinmycheeks dot com]
 *
 *	@param: Object Array. Arguments need to be in object notation.
 *	Returns: jQuery.
 *	Options:
 *		param:		What css color option you wish to fade.
 *					Such as "background-color", "color", "boarder-color", "scrollbar-face-color" etc.
 *					(default: "background-color).
 *		fps:		Frames per second (default: 30).
 *		cycles:		How many times you want the object to fade. 0 = Infinite. (default: 0).
 *		random:		Will transition from a random color to a random color. (default: false).
 *					Note: Will change isFade to false.
 *		isFade:		Will fade from the original color and back to the original color. (default: true).
 *					Note: Cannont set to true if random is set to true.
 *		fromColor:	*DEPRECIATED* Starting color. accepts RGB, Hex, Name values.
 *					Will be overwritten if random is set to true. Also accepts "random" as an option.
 *		toColor:	*DEPRECIATED* Ending color. Same as above.
 *		colorList:	Now accepts an array of color strings! colorList can accept 3 or 6 digit hex colors (#000000, #000) it can also accept rgb and color names.
 *		alpha:		Opacity of element! accepts numerical array and old comma seperated string. (Default: [100, 100]).
 *		isQueue:	Will queue up color aniimations for a paramater.
 *	Examples:
 *		$("body").colorBlend([{fromColor:"black", toColor:"white", param:"color"}]);
 *		var myColors = [
 *			{param:'color', colorList["white", "black"]},
 *			{param:'background-color', random: true, alpha:[20,75]},
 *			{param:'border-left-color', colorList: ["random", "black"]},
 *			{param:'border-right-color', fromColor:"white", "black"]},
 *			{param:'border-top-color', colorList: ["white", "black", "pink"]},
 *			{param:'border-bottom-color', colorList: ["white", "tomato", "lime"]}
 *		];
 *		$("tr").colorBlend(myColors);
 *
 *	Known issues:
 *			* If used on a lot of objects it can cause major browser slowdown and it will eat a lot of cpu.
 *			* Still one flickering bug when it comes to opacity. Trying to track it down.
 *
 *	Additions:
 *		1.0.2
 *			* Added "parent" as a valid color value. Will check parents until valid color is found.
 *				defaults to white if there are no parents with color.
 *		1.0.3
 *			* Added Alpha/Opacity blending! Add alpha:"0,100" to list of parameters.
 *				Note: Will change the opacity of element only, not the property!
 *				If you only want text to appear and dissapear, you'll have to put it in it's own element, otherise the whole
 *				element will fade, not just your text.
 *		1.0.4
 *			* Alpha will now take just one argument alpha:"30" if you want to just change the alpha and not have it animate.
 *			* Current is now the default fromColor value. The current value will get the current color of the element. If current is transparent, it will get the parent color.
 *			* Opposite is now the default toColor value.
 *
 *		1.3.0
 *			* Added Queueing ability, so an animation will take arguments and process them once they are available.
 *			* Added Action parameter available arguments are stop, pause, and resume. Resume continues a paused animation. Where stop lets you assign a whole new animation to the element.
 *			* Added isQueue as an option allows you to decide if you want an option to be queued or not
 *
 *		1.4.0
 *			* Added pause all, stop all, resume all.
 *			* Have objects stored in an non-named array for traversing.
 *		1.6.0
 *			* Changed some internals for smaller quicker code.
 *			* Added colorList. fromColor and toColor still work, but they are just converted into a colorList.
 *			* Changed alpha to an array as well, can use more than 2 params. Still works with older string based param.
 *	Bugs fixed:
 *		1.0.1
 *			* Undesired flickering effect if colorBlend was called multiple times on the same css parameter.
 *		1.0.2
 *			* Noticed element would keep color attributes in certain circumstances.
 *		1.0.4
 *			* Fixed bug where under certain conditions the color would flicker.
 *		1.0.5
 *			* Great find by cratchit and he supplied the fix. Can now call colorBlend without any options.
 *		1.2.0
 *			* Flicker fix in 1.0.4 caused other issues. Fixed for good.
 *			* Found that if you try to get current color from scroll bar, it blows up. Added check for undefined as a color. Defaults to white.
 *		1.3.0
 *			* Found MORE flickering issues, and fixed them. I guess it's not over until the fat lady sings. Didn't see any more flicking, but I don't hear a fat lady.
 *		1.5.0
 *			* In my ignorance I noticed that alpha is taken care of quite nicely by jquery itself. No need to fix what isn't broke. Removed the custom stuff I had placed in.
 *			* Found an issue where if pausing and resuming something repeatitivly it might not sync up and cause weird flashing effects. Added isPOrS variable to check if paused or stopped. Seems to work.
 *		1.6.1
 *			* Found that in my last release I had accidentally hosed the "current", "random", "parent" and "opposite" options for the color list.
 */

(function($) {
	var ver = '1.6.1';
	var gObj = [];
	var q = 0;
	var tfps = [];
	var cnt = 0;
	var cid = 0;

	$.fn.colorBlend = function(opts) {
		if(!opts) { opts = [{}]; }

		var arrySelected = [];
		this.each(function() {
			arrySelected[arrySelected.length] = $.data($(this).get(0));
		});

		return this.each(function() {
			var $cont = $(this);
			var uId = $.data($cont.get(0));
			var isFlagAll = false;

			if(udf(gObj[uId])) {
				gObj[uId] = [];
			}

			$.each(opts, function(i, v){
				var isFound = false;
				opts[i] = $.extend({}, $.fn.colorBlend.defaults, opts[i]);
				opts[i].queue = [];
				opts[i].internals = $.extend({}, $.fn.colorBlend.internals);
				opts[i].parent = $cont;

				if(opts[i].param == "all") {
					isFlagAll = FlagAll(opts[i].action);
				}

				$.each(gObj[uId], function(j, w) {
					if(gObj[uId][j].param.toLowerCase() == opts[i].param.toLowerCase()
					|| opts[i].param.toLowerCase() == 'all') {
						if(!gObj[uId][j].internals.animating) {
							gObj[uId].splice(j, 1, setOptions(opts[i]));
						}
						isFound = true;
						return false;
					}
				});

				if(!isFound) {
					gObj[uId].push(setOptions(opts[i]));
				}
			});

			if(!isFlagAll) {
				$.each(gObj[uId], function(i, v){
					var ani = gObj[uId][i].internals.animating;
					var pausedOrStopped = gObj[uId][i].internals.isPOrS;

					$.each(opts, function(j, w) {
						if(gObj[uId][i].param.toLowerCase() != opts[j].param.toLowerCase()) {
							return true;
						}

						switch(opts[j].action) {
							case "stop":
							case "pause":
								clearTimeout(gObj[uId][i].internals.tId);
								gObj[uId][i].internals.isPOrS = true;
								pausedOrStopped = true;
								if(opts[j].action == "stop") {
									gObj[uId][i].internals.animating = false;
								}
							break;
							case "resume":
								ani = true;
								pausedOrStopped = false;
								gObj[uId][i].internals.isPOrS = false;
								go(gObj[uId][i]);
							break;
							default:
								if(ani) {
									if(gObj[uId][i].isQueue && gObj[uId][i].cycles > 0) {
										gObj[uId][i].queue.push(setOptions(opts[j]));
									}
								}
							break;
						}
					});

					if(!ani && !pausedOrStopped) {
						go(gObj[uId][i]);
					}
				});
			}
		});

		function FlagAll(action) {
			var res = false;
			$.each(arrySelected, function(i, v) {
				var curObj = gObj[v];
				$.each(curObj, function(j, w) {
					switch(action) {
						case "stop":
						case "pause":
							res = true;
							clearTimeout(curObj[j].internals.tId);
							curObj[j].internals.isPOrS = true;
							if(action == "stop") {
								curObj[j].internals.animating = false;
							}
						break;
						case "resume":
							res = true;
							curObj[j].internals.isPOrS = false;
							go(curObj[j]);
						break;
					}
				});
			});

			return res;
		};
	};

	$.fn.colorBlend.defaults = {
		fps:30,
		duration:1000,
		param:"background-color",
		cycles:0,
		random:false,
		isFade:true,
		fromColor:"",
		toColor:"",
		colorList: ["current", "opposite"],
		alpha:["100", "100"],
		action:"",
		isQueue:true
	};

	$.fn.colorBlend.internals = {
		aniArray:  [],
		alphaArry: [],
		pos: 0,
		currentCycle: 0,
		direction: 1,
		frames: 0,
		delay: 0,
		fromRand: false,
		toRand: false,
		animating: false,
		tId: 0,
		isPOrS: false
	};

	function setOptions(Opts) {
		if(!Opts.internals.animating) {
			var alphaParam = typeof(Opts.alpha) == "string" ? Opts.alpha.split(",") : Opts.alpha;

			if(Opts.fromColor != "" && Opts.toColor != "") {
				switch(Opts.fromColor.toLowerCase()) {
					case "current":
						Opts.fromColor = Opts.parent.css(Opts.param);
						break;
					case "parent":
					case "transparent":
						Opts.fromColor = checkParentColor(Opts.parent, Opts.param);
						break;
					case "opposite":
						Opts.fromColor = OppositeColor(Opts.toColor);
						break;
					case "random":
						Opts.fromColor = rndColor();
						Opts.internals.fromRand = true;
						break;
				}

				switch(Opts.toColor.toLowerCase()) {
					case "current":
						Opts.toColor = Opts.parent.css(Opts.param);
						break;
					case "parent":
					case "transparent":
						Opts.toColor = checkParentColor(Opts.parent, Opts.param);
						break;
					case "opposite":
						Opts.toColor = OppositeColor(Opts.fromColor);
						break;
					case "random":
						Opts.toColor = rndColor();
						Opts.internals.toRand = true;
						break;
				}

				Opts.colorList = [Opts.fromColor, Opts.toColor];
			}

			if(Opts.colorList.length == 1) {
				if(Opts.colorList[0].toLowerCase() == "random") {
					Opts.internals.toRand = true;
					Opts.colorList[0] = rndColor();
				}
			}

			$.each(Opts.colorList, function(i, v) {
				switch(v.toLowerCase()) {
					case "current":
						Opts.colorList[i] = Opts.parent.css(Opts.param) == "transparent" ? checkParentColor(Opts.parent, Opts.param) : Opts.parent.css(Opts.param);
						break;
					case "parent":
					case "transparent":
						Opts.colorList[i] = checkParentColor(Opts.parent, Opts.param);
						break;
					case "opposite":
						Opts.colorList[i] = OppositeColor(toHexColor(checkParentColor(Opts.parent, Opts.param)));
						break;
					case "random":
						Opts.colorList[i] = rndColor();
						break;
				}
			});

			Opts.internals.currentCycle = Opts.cycles > 0 ? Opts.cycles : 0;
			Opts.internals.frames = Math.floor(Opts.fps * (Opts.duration / 1000));
			Opts.internals.delay = Math.floor(Opts.duration / ((Opts.internals.frames+1)*Opts.colorList.length));

			if(Opts.random) {
				Opts.isFade = false;
				Opts.colorList = [rndColor(), rndColor()];
			}

			if(Opts.isFade) {
				Opts.internals.currentCycle = Opts.internals.currentCycle * 2;
				Opts.internals.delay = Math.floor(Opts.internals.delay / 2);
				Opts.internals.frames = Math.floor(Opts.internals.frames / 2);
			}

			Opts.internals.alphaArry = buildAlphaAni(alphaParam, Opts.internals.frames);
			Opts.internals.aniArray = buildAnimation(Opts.colorList, Opts.internals.frames);
			return Opts;
		}
	}

	function go(Opts) {
		if(!Opts.internals.isPOrS) {
			var sendStop = false;

			Opts.internals.animating = true;

			Opts.parent.css(Opts.param, Opts.internals.aniArray[Opts.internals.pos]);
			setAlpha(Opts.parent, Opts.internals.alphaArry[Opts.internals.pos]);

			Opts.internals.pos += Opts.internals.direction;

			if(Opts.internals.pos < 0 || Opts.internals.pos >= Opts.internals.aniArray.length) {
				Opts.internals.currentCycle -= Opts.internals.currentCycle != 0 ? 1 : 0;
				Opts.internals.direction = Opts.internals.direction * -1;
				Opts.internals.pos += Opts.internals.direction;

				if(Opts.random) {
					Opts.colorList = [Opts.colorList[Opts.colorList.length-1], rndColor()];
					Opts.internals.aniArray = buildAnimation(Opts.colorList, Opts.internals.frames);
				}

				if(!Opts.isFade) {
					Opts.internals.direction = 1;
					Opts.internals.pos = 0;
				}

				if(Opts.internals.currentCycle == 0 && Opts.cycles > 0) {
					sendStop = true;
				}
			}

			if(!sendStop) {
				Opts.internals.tId = setTimeout(function(){go(Opts);}, Opts.internals.delay);
			} else {
				clearTimeout(Opts.internals.tId);
				Opts.internals.tId = 0;
				if(Opts.isQueue && Opts.queue.length > 0) {
					var tmp = Opts.queue.concat();
					tmp.splice(0,1);
					Opts = $.extend(Opts, Opts.queue.shift());
					Opts.queue = tmp.concat();
					Opts.internals.tId = setTimeout(function(){go(Opts);}, Opts.internals.delay);
				} else {
					Opts.internals.animating = false;
					Opts.internals.isPOrS = true;
				}
			}
		}
	}

	function setAlpha(elm, opacity) {
		elm.css("opacity", parseFloat(opacity / 100));
	}

	function buildAlphaAni(alphaList, frames) {
		var frame = 0;
		var res = [];
		var h = 0;

		for(var i = 0;i < alphaList.length-1;i++) {
			var startOpacity = alphaList[i];
			var endOpacity = alphaList[i+1];
			for(frame = 0;frame<=frames;frame++) {
				h = Math.floor(startOpacity * ((frames-frame)/frames) + endOpacity * (frame/frames));
				res[res.length] = h
			}
		}

		if(h != alphaList[alphaList.length-1]) {
			res[res.length] = parseInt(alphaList[alphaList.length-1]);
		}

		return res;
	}

	function buildAnimation(colorList, frames) {
		var frame = 0;
		var r,g,b,h;
		var res = [];
		for(var i = 0;i < colorList.length-1;i++) {
			var fc = getRGB(colorList[i]);
			var tc = getRGB(colorList[i+1]);

			for(frame = 0;frame<=frames;frame++) {
				r = Math.floor(fc[0] * ((frames-frame)/frames) + tc[0] * (frame/frames));
				g = Math.floor(fc[1] * ((frames-frame)/frames) + tc[1] * (frame/frames));
				b = Math.floor(fc[2] * ((frames-frame)/frames) + tc[2] * (frame/frames));
				h = ColorDecToHex(r, g, b);
				res[res.length] = h;
			}
		}


		if(h.toLowerCase() != toHexColor(colorList[colorList.length-1])) {
			res[res.length] = toHexColor(colorList[colorList.length-1]);
		}

		return res;
	}

	var colors = {
		aliceblue:"F0F8FF", antiquewhite:"FAEBD7", aqua:"00FFFF", aquamarine:"7FFFD4",
		azure:"F0FFFF", beige:"F5F5DC", bisque:"FFE4C4", black:"000000",
		blanchedalmond:"FFEBCD", blue:"0000FF", blueviolet:"8A2BE2", brown:"A52A2A",
		burlywood:"DEB887", cadetblue:"5F9EA0", chartreuse:"7FFF00", chocolate:"D2691E",
		coral:"FF7F50", cornflowerblue:"6495ED", cornsilk:"FFF8DC", crimson:"DC143C",
		cyan:"00FFFF", darkblue:"00008B", darkcyan:"008B8B", darkgoldenrod:"B8860B",
		darkgray:"A9A9A9", darkgreen:"006400", darkkhaki:"BDB76B", darkmagenta:"8B008B",
		darkolivegreen:"556B2F", darkorange:"FF8C00", darkorchid:"9932CC", darkred:"8B0000",
		darksalmon:"E9967A", darkseagreen:"8FBC8F", darkslateblue:"483D8B", darkslategray:"2F4F4F",
		darkturquoise:"00CED1", darkviolet:"9400D3", deeppink:"FF1493", deepskyblue:"00BFFF",
		dimgray:"696969", dodgerblue:"1E90FF", firebrick:"B22222", floralwhite:"FFFAF0",
		forestgreen:"228B22", fuchsia:"FF00FF", gainsboro:"DCDCDC", ghostwhite:"F8F8FF",
		gold:"FFD700", goldenrod:"DAA520", gray:"808080", grey:"808080", green:"008000",
		greenyellow:"ADFF2F", honeydew:"F0FFF0", hotpink:"FF69B4", indianred:"CD5C5C",
		indigo:"4B0082", ivory:"FFFFF0", khaki:"F0E68C", lavender:"E6E6FA",
		lavenderblush:"FFF0F5", lawngreen:"7CFC00", lemonchiffon:"FFFACD", lightblue:"ADD8E6",
		lightcoral:"F08080", lightcyan:"E0FFFF", lightgoldenrodyellow:"FAFAD2", lightgreen:"90EE90",
		lightgrey:"D3D3D3", lightpink:"FFB6C1", lightsalmon:"FFA07A", lightseagreen:"20B2AA",
		lightskyblue:"87CEFA", lightslategray:"778899", lightsteelblue:"B0C4DE", lightyellow:"FFFFE0",
		lime:"00FF00", limegreen:"32CD32", linen:"FAF0E6", magenta:"FF00FF",
		maroon:"800000", mediumaquamarine:"66CDAA", mediumblue:"0000CD", mediumorchid:"BA55D3",
		mediumpurple:"9370DB", mediumseagreen:"3CB371", mediumslateblue:"7B68EE", mediumspringgreen:"00FA9A",
		mediumturquoise:"48D1CC", mediumvioletred:"C71585", midnightblue:"191970", mintcream:"F5FFFA",
		mistyrose:"FFE4E1", moccasin:"FFE4B5", navajowhite:"FFDEAD", navy:"000080",
		oldlace:"FDF5E6", olive:"808000", olivedrab:"6B8E23", orange:"FFA500",
		orangered:"FF4500", orchid:"DA70D6", palegoldenrod:"EEE8AA", palegreen:"98FB98",
		paleturquoise:"AFEEEE", palevioletred:"DB7093", papayawhip:"FFEFD5", peachpuff:"FFDAB9",
		peru:"CD853F", pink:"FFC0CB", plum:"DDA0DD", powderblue:"B0E0E6",
		purple:"800080", red:"FF0000", rosybrown:"BC8F8F", royalblue:"4169E1",
		saddlebrown:"8B4513", salmon:"FA8072", sandybrown:"F4A460", seagreen:"2E8B57",
		seashell:"FFF5EE", sienna:"A0522D", silver:"C0C0C0", skyblue:"87CEEB",
		slateblue:"6A5ACD", slategray:"708090", snow:"FFFAFA", springgreen:"00FF7F",
		steelblue:"4682B4", tan:"D2B48C", teal:"008080", thistle:"D8BFD8",
		tomato:"FF6347", turquoise:"40E0D0", violet:"EE82EE", wheat:"F5DEB3",
		white:"FFFFFF", whitesmoke:"F5F5F5", yellow:"FFFF00", yellowgreen:"9ACD32"
	};

	function OppositeColor(value) {
		value = toHexColor(value).split("#").join('').split('');
		var hexVals = "0123456789abcdef";
		var revHexs = hexVals.split('').reverse().join('');
		var currentPos;
		for(var i = 0;i < value.length;i++) {
			currentPos = hexVals.indexOf(value[i]);
			value[i] = revHexs.substring(currentPos,currentPos+1);
		}

		return "#" + value.join('');
	}

	function ColorDecToHex(r,g,b) {
		r = r.toString(16); if (r.length == 1) r = '0' + r;
		g = g.toString(16); if (g.length == 1) g = '0' + g;
		b = b.toString(16); if (b.length == 1) b = '0' + b;
		return "#" + r + g + b;
	}

	function ColorHexToDec(value) {
		var res = [];
		value = value.replace("#", "");
		for(var i = 0;i < 3;i++) {
			res[res.length] = parseInt(value.substr(i * 2, 2), 16);
		}
		return res.join(',');
	}

	// Color Conversion functions from highlightFade
	// By Blair Mitchelmore
	// http://jquery.offput.ca/highlightFade/
	// Parse strings looking for color tuples [255,255,255]
	function getRGB(color) {
		var result;

		// Check if we're already dealing with an array of colors
		if ( color && color.constructor == Array && color.length == 3 )
			return color;

		// Look for rgb(num,num,num)
		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
			return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])];

		// Look for rgb(num%,num%,num%)
		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
			return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];

		// Look for #a0b1c2
		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
			return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];

		// Look for #fff
		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
			return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];

		// Otherwise, we're most likely dealing with a named color
		return ColorHexToDec(colors[jQuery.trim(color).toLowerCase()]).split(',');
	}

	function toHexColor(value) {
		var rgb = getRGB(value);
		return ColorDecToHex(parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2]));
	}

	function checkParentColor(elm, param) {
		/*White is chosen as default to eliminate issues between IE and FF*/
		var pColr = "#ffffff";

		$(elm).parents().each(function(){
			var result = $(this).css(param);
			if(result != 'transparent' && result != '') {
				pColr = result;
				return false;
			}
		});

		return pColr;
	}

	function rndColor() {
		var res = [];
		var cm;
		for(var i = 0;i < 3;i++) {
			cm = randRange(0, 255).toString(16);
			if (cm.length == 1) cm = '0' + cm;
			res[res.length] = cm;
		}
		return "#" + res.join('');
	}

	function randRange(lowVal, highVal) {
		 return Math.floor(Math.random()*(highVal-lowVal+1))+lowVal;
	}

	function udf(val) {
		return typeof(val) == 'undefined' ? true : false;
	}
})(jQuery);
/*
 * jQuery FlyOut
 * author: Jolyon Terwilliger - Nixbox Web Designs
 * website: http://nixboxdesigns.com/jquery.flyout.php
 */

$.fn.extend({flyout : function(options) {
	
		var shown=false;
		var animating=false;
		var $holder;
		var $thumb;
		var tloc;
		var th;
		var tw;
		var bigimg = new Image();
		var subType = 'img';
		var offset;
        var id = this.id;
		
		this.click(function() {
			if (animating == true) { return false; }
	
			if (shown) { putAway(this); }
			else { flyOut(this); }
	
			return false;
		});

		jQuery(document).click(function() {
			if (animating == true) { return false; }
			if (shown) { putAway(id); return false;}
		});
		
		var o = jQuery.extend({
			outSpeed : 1000,
			inSpeed : 500,
			outEase : 'swing',
			inEase : 'swing',
			loadingSrc: null,
			loader: 'loaderMini',
			loaderZIndex: 500,
			widthMargin: 40,
			heightMargin: 40,
			loadingText : "Ładowanie...",
			closeTip : " - Kliknij w obrazek aby go ukryć",
			destPadding: 20,
			startOffsetX: 0,
			startOffsetY: 0,
			startHeight: 0,
			startWidth: 0,
			flyOutStart: function() {},
			flyOutFinish: function() {},
			putAwayStart: function() {},
			putAwayFinish: function() {},
			shownClass: 'shown'
		}, options);
	
		function flyOut(it) {
			animating = true;
			
			$holder = $(it);
			$thumb = $('img',it);
			bigimg = new Image(); 
			sL = $(window).scrollLeft();
			sT = $(window).scrollTop();
			tloc = $thumb.offset();
			tloc.left += o.startOffsetX;
			tloc.top += o.startOffsetY;
			th = (o.startHeight > 0 ? o.startHeight : $thumb.height());
			tw = (o.startWidth > 0 ? o.startWidth : $thumb.width());
			
			$('<div></div>').attr('id',o.loader)
							.appendTo('body')
							.css({'position':'absolute',
								'top':tloc.top,
								'left':tloc.left,
								'height':th,
								'width':tw,
								'opacity':.5,
								'display':'block',
								'z-index':o.loaderZIndex});

			if (o.loadingSrc) {
				$('#'+o.loader).append($('<img/>')
								.load(function() {
										$(this)
											.css({'position':'relative',
												 'top':th/2-(this.height/2),
												 'left':tw/2-(this.width/2)})
											.attr('alt',o.loadingText);
										})
									.attr('src',o.loadingSrc)
								);
			}
			else {
				$('#'+o.loader).css('background-color','#000')
								.append($('<span></span>')
										  	.text(o.loadingText)
											.css({'position':'relative',
												 'top':'2px',
												 'left':'2px',
												 'color':'#FFF',
												 'font-size':'9px'})
									 	);
			}

			$(bigimg).load(function() {
				imgtag = $('<img/>').attr('src',$holder.attr('href')).attr('title',$thumb.attr('title')+o.closeTip).attr('alt',$thumb.attr('alt')+o.closeTip).height(th).width(tw);

				o.flyOutStart.call(it);

				if (o.destElement) {
					var $dest = $(o.destElement);
					max_x = $dest.innerWidth() - (o.destPadding*2);
					max_y = $dest.innerHeight() - (o.destPadding*2);
				}
				else {
					max_x = $(window).width()-o.widthMargin;
					if ($.browser.opera) 
						wh = document.getElementsByTagName('html')[0].clientHeight;
					else 
						wh = $(window).height();
					max_y = wh-o.heightMargin;
				}

				width = bigimg.width;
				height = bigimg.height;
	
				x_dim = max_x / width;
				y_dim = max_y / height;
	
				if (x_dim <=y_dim) {
					y_dim = x_dim;
				} else {
					x_dim = y_dim;
				}
				
				dw = Math.round(width  * x_dim);
				dh = Math.round(height * y_dim);
				if (dw>width) {dw = width}
				if (dh>height) {dh = height}
				
				if (o.destElement) {
					dPos = $dest.offset();
					dl = Math.round(($dest.outerWidth()/2)-(dw/2)+dPos.left);
					dt = Math.round(($dest.outerHeight()/2)-(dh/2)+dPos.top);
				}
				else {
					dl = Math.round(($(window).width()/2)-(dw/2)+sL);
					if ($.browser.opera) 
						wh = document.getElementsByTagName('html')[0].clientHeight;
					else 
						wh = $(window).height();
					dt = Math.round((wh/2)-(dh/2)+sT);
				}
				
				$('#'+o.loader).empty().css('opacity',1).append(imgtag).width('auto').height('auto').animate({top:dt, left:dl},{duration:o.outSpeed, queue:false, easing:o.outEase});
				$('#'+o.loader+' '+subType).animate({height:dh, width:dw}, o.outSpeed, o.outEase,
				function() {
					o.flyOutFinish.call(it);
					shown = it;
					$holder.addClass(o.shownClass);
					animating=false;
					$('#'+o.loader+' '+subType).click(function(){putAway(null)})
				});
			});
			bigimg.src = $holder.attr('href');
		}
	
	
		function putAway(next) {
			// for future development:
			if (animating == true || shown == false) {return false;}
			o.putAwayStart.call(shown);
			
			animating = true;
			
			// check $thumb loc again, in case it moved...
			tloc = $thumb.offset();
			tloc.left += o.startOffsetX;
			tloc.top += o.startOffsetY;

			$('#'+o.loader).animate({top:tloc.top, left:tloc.left},{duration:o.inSpeed, queue:false, easing:o.inEase});
			$('#'+o.loader+' '+subType).animate({height:th, width:tw}, 
				o.inSpeed, o.inEase, 
				function() {
					$('#'+o.loader).css('display','none').remove(); 
					o.putAwayFinish.call(shown);
					animating=false;
					bigimg=null;			
					if (next && next != shown) {
						shown = false;
						flyOut(next);
					}
					shown = false;
					$holder.removeClass(o.shownClass);
				});
		}
		
		return this;	// never break the chain
		
	}
});
/**
 * jQuery.Preload
 * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com
 * Dual licensed under MIT and GPL.
 * Date: 3/12/2008
 *
 * @projectDescription Multifunctional preloader
 * @author Ariel Flesler
 * @version 1.0.7
 *
 * @id jQuery.preload
 * @param {String, jQuery, Array< String, <a>, <link>, <img> >} original Collection of sources to preload
 * @param {Object} settings Hash of settings.
 *
 * @id jQuery.fn.preload
 * @param {Object} settings Hash of settings.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * @example Link Mode:
 *	$.preload( '#images a' );
 *
 * @example Rollover Mode:
 *	$.preload( '#images img', {
 *		find:/\.(gif|jpg)/,
 *		replace:'_over.$1'
 *	});
 *
 * @example Src Mode:
 *	$.preload( [ 'red', 'blue', 'yellow' ], {
 *		base:'images/colors/',
 *		ext:'.jpg'
 *	});
 *
 * @example Placeholder Mode:
 *	$.preload( '#images img', {
 *		placeholder:'placeholder.jpg',
 *		notFound:'notfound.jpg'
 *	});
 *
 * @example Placeholder+Rollover Mode(High res):
 *	$.preload( '#images img', {
 *		placeholder:true,
 *		find:/\.(gif|jpg)/,
 *		replace:'_high.$1'
 *	});
 */
;(function( $ ){

	var $preload = $.preload = function( original, settings ){
		if( original.split )//selector
			original = $(original);

		settings = $.extend( {}, $preload.defaults, settings );
		var sources = $.map( original, function( source ){
			if( !source ) 
				return;//skip
			if( source.split )//URL Mode
				return settings.base + source + settings.ext;
			var url = source.src || source.href;//save the original source
			if( typeof settings.placeholder == 'string' && source.src )//Placeholder Mode, if it's an image, set it.
				source.src = settings.placeholder;
			if( url && settings.find )//Rollover mode
				url = url.replace( settings.find, settings.replace );
			return url || null;//skip if empty string
		});

		var data = {
			loaded:0,//how many were loaded successfully
			failed:0,//how many urls failed
			next:0,//which one's the next image to load (index)
			done:0,//how many urls were tried
			//found:false,//whether the last one was successful
			total:sources.length//how many images are being preloaded overall
		};
		
		if( !data.total )//nothing to preload
			return finish();
		
		var imgs = '<img/>',//ensure one
			thres = settings.threshold;//save a copy
		
		while( --thres > 0 )//it could be oddly negative
			imgs += '<img/>';
		imgs = $(imgs).load(handler).error(handler).bind('abort',handler).each(fetch);
		
		function handler( e ){
			data.found = e.type == 'load';
			data.image = this.src;
			var orig = data.original = original[this.index];
			data[data.found?'loaded':'failed']++;
			data.done++;
			if( settings.placeholder && orig.src )//special case when on placeholder mode
				orig.src = data.found ? data.image : settings.notFound || orig.src;
			if( settings.onComplete )
				settings.onComplete( data );
			if( data.done < data.total )//let's continue
				fetch( 0, this );
			else{//we are finished
				if( imgs.unbind )//sometimes IE gets here before finishing line 84
					imgs.unbind('load').unbind('error').unbind('abort');//cleanup
				imgs = null;
				finish();
			}
		};
		function fetch( i, img, retry ){
			if( $.browser.msie && data.next && data.next % $preload.gap == 0 && !retry ){//IE problem, can't preload more than 15
				setTimeout(function(){ fetch( i, img, true ); }, 0);
				return false;
			}
			if( data.next == data.total ) return false;//no more to fetch
			img.index = data.next;//save it, we'll need it.
			img.src = sources[data.next++];
			if( settings.onRequest ){
				data.image = img.src;
				data.original = original[data.next-1];
				settings.onRequest( data );
			}
		};
		function finish(){
			if( settings.onFinish )
				settings.onFinish( data );
		};
	};

	// each time we load this amount and it's IE, we must rest for a while, make it lower if you get stack overflow.
	$preload.gap = 14; 

	$preload.defaults = {
		threshold:2,//how many images to load simultaneously
		base:'',//URL mode: a base url can be specified, it is prepended to all string urls
		ext:'',//URL mode:same as base, but it's appended after the original url.
		replace:''//Rollover mode: replacement (can be left empty)
		/*
		find:null,//Rollover mode: a string or regex for the replacement
		notFound:''//Placeholder Mode: Optional url of an image to use when the original wasn't found
		placeholder:'',//Placeholder Mode: url of an image to set while loading
		onRequest:function( data ){ ... },//callback called every time a new url is requested
		onComplete:function( data ){ ... },//callback called every time a response is received(successful or not)
		onFinish:function( data ){ ... }//callback called after all the images were loaded(or failed)
		*/
	};

	$.fn.preload = function( settings ){
		$preload( this, settings );
		return this;
	};

})( jQuery );/*
 * jQuery Form Plugin
 * version: 2.25 (08-APR-2009)
 * @requires jQuery v1.2.2 or later
 *
 * Examples and documentation at: http://malsup.com/jquery/form/
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */
;(function($) {

/*
    Usage Note:
    -----------
    Do not use both ajaxSubmit and ajaxForm on the same form.  These
    functions are intended to be exclusive.  Use ajaxSubmit if you want
    to bind your own submit handler to the form.  For example,

    $(document).ready(function() {
        $('#myForm').bind('submit', function() {
            $(this).ajaxSubmit({
                target: '#output'
            });
            return false; // <-- important!
        });
    });

    Use ajaxForm when you want the plugin to manage all the event binding
    for you.  For example,

    $(document).ready(function() {
        $('#myForm').ajaxForm({
            target: '#output'
        });
    });

    When using ajaxForm, the ajaxSubmit function will be invoked for you
    at the appropriate time.
*/

/**
 * ajaxSubmit() provides a mechanism for immediately submitting
 * an HTML form using AJAX.
 */
$.fn.ajaxSubmit = function(options) {
    // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
    if (!this.length) {
        log('ajaxSubmit: skipping submit process - no element selected');
        return this;
    }

    if (typeof options == 'function')
        options = { success: options };

    // clean url (don't include hash vaue)
    var url = this.attr('action') || window.location.href;
    url = (url.match(/^([^#]+)/)||[])[1];
    url = url || '';

    options = $.extend({
        url:  url,
        type: this.attr('method') || 'GET'
    }, options || {});

    // hook for manipulating the form data before it is extracted;
    // convenient for use with rich editors like tinyMCE or FCKEditor
    var veto = {};
    this.trigger('form-pre-serialize', [this, options, veto]);
    if (veto.veto) {
        log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
        return this;
    }

    // provide opportunity to alter form data before it is serialized
    if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
        log('ajaxSubmit: submit aborted via beforeSerialize callback');
        return this;
    }

    var a = this.formToArray(options.semantic);
    if (options.data) {
        options.extraData = options.data;
        for (var n in options.data) {
          if(options.data[n] instanceof Array) {
            for (var k in options.data[n])
              a.push( { name: n, value: options.data[n][k] } );
          }
          else
             a.push( { name: n, value: options.data[n] } );
        }
    }

    // give pre-submit callback an opportunity to abort the submit
    if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
        log('ajaxSubmit: submit aborted via beforeSubmit callback');
        return this;
    }

    // fire vetoable 'validate' event
    this.trigger('form-submit-validate', [a, this, options, veto]);
    if (veto.veto) {
        log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
        return this;
    }

    var q = $.param(a);

    if (options.type.toUpperCase() == 'GET') {
        options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
        options.data = null;  // data is null for 'get'
    }
    else
        options.data = q; // data is the query string for 'post'

    var $form = this, callbacks = [];
    if (options.resetForm) callbacks.push(function() { $form.resetForm(); });
    if (options.clearForm) callbacks.push(function() { $form.clearForm(); });

    // perform a load on the target only if dataType is not provided
    if (!options.dataType && options.target) {
        var oldSuccess = options.success || function(){};
        callbacks.push(function(data) {
            $(options.target).html(data).each(oldSuccess, arguments);
        });
    }
    else if (options.success)
        callbacks.push(options.success);

    options.success = function(data, status) {
        for (var i=0, max=callbacks.length; i < max; i++)
            callbacks[i].apply(options, [data, status, $form]);
    };

    // are there files to upload?
    var files = $('input:file', this).fieldValue();
    var found = false;
    for (var j=0; j < files.length; j++)
        if (files[j])
            found = true;

    // options.iframe allows user to force iframe mode
   if (options.iframe || found) {
       // hack to fix Safari hang (thanks to Tim Molendijk for this)
       // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
       if (options.closeKeepAlive)
           $.get(options.closeKeepAlive, fileUpload);
       else
           fileUpload();
       }
   else
       $.ajax(options);

    // fire 'notify' event
    this.trigger('form-submit-notify', [this, options]);
    return this;


    // private function for handling file uploads (hat tip to YAHOO!)
    function fileUpload() {
        var form = $form[0];

        if ($(':input[name=submit]', form).length) {
            alert('Error: Form elements must not be named "submit".');
            return;
        }

        var opts = $.extend({}, $.ajaxSettings, options);
		var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts);

        var id = 'jqFormIO' + (new Date().getTime());
        var $io = $('<iframe id="' + id + '" name="' + id + '" src="about:blank" />');
        var io = $io[0];

        $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });

        var xhr = { // mock object
            aborted: 0,
            responseText: null,
            responseXML: null,
            status: 0,
            statusText: 'n/a',
            getAllResponseHeaders: function() {},
            getResponseHeader: function() {},
            setRequestHeader: function() {},
            abort: function() {
                this.aborted = 1;
                $io.attr('src','about:blank'); // abort op in progress
            }
        };

        var g = opts.global;
        // trigger ajax global events so that activity/block indicators work like normal
        if (g && ! $.active++) $.event.trigger("ajaxStart");
        if (g) $.event.trigger("ajaxSend", [xhr, opts]);

		if (s.beforeSend && s.beforeSend(xhr, s) === false) {
			s.global && $.active--;
			return;
        }
        if (xhr.aborted)
            return;

        var cbInvoked = 0;
        var timedOut = 0;

        // add submitting element to data if we know it
        var sub = form.clk;
        if (sub) {
            var n = sub.name;
            if (n && !sub.disabled) {
                options.extraData = options.extraData || {};
                options.extraData[n] = sub.value;
                if (sub.type == "image") {
                    options.extraData[name+'.x'] = form.clk_x;
                    options.extraData[name+'.y'] = form.clk_y;
                }
            }
        }

        // take a breath so that pending repaints get some cpu time before the upload starts
        setTimeout(function() {
            // make sure form attrs are set
            var t = $form.attr('target'), a = $form.attr('action');

			// update form attrs in IE friendly way
			form.setAttribute('target',id);
			if (form.getAttribute('method') != 'POST')
				form.setAttribute('method', 'POST');
			if (form.getAttribute('action') != opts.url)
				form.setAttribute('action', opts.url);

            // ie borks in some cases when setting encoding
            if (! options.skipEncodingOverride) {
                $form.attr({
                    encoding: 'multipart/form-data',
                    enctype:  'multipart/form-data'
                });
            }

            // support timout
            if (opts.timeout)
                setTimeout(function() { timedOut = true; cb(); }, opts.timeout);

            // add "extra" data to form if provided in options
            var extraInputs = [];
            try {
                if (options.extraData)
                    for (var n in options.extraData)
                        extraInputs.push(
                            $('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />')
                                .appendTo(form)[0]);

                // add iframe to doc and submit the form
                $io.appendTo('body');
                io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
                form.submit();
            }
            finally {
                // reset attrs and remove "extra" input elements
				form.setAttribute('action',a);
                t ? form.setAttribute('target', t) : $form.removeAttr('target');
                $(extraInputs).remove();
            }
        }, 10);

        var nullCheckFlag = 0;

        function cb() {
            if (cbInvoked++) return;

            io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);

            var ok = true;
            try {
                if (timedOut) throw 'timeout';
                // extract the server response from the iframe
                var data, doc;

                doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;

                if ((doc.body == null || doc.body.innerHTML == '') && !nullCheckFlag) {
                    // in some browsers (cough, Opera 9.2.x) the iframe DOM is not always traversable when
                    // the onload callback fires, so we give them a 2nd chance
                    nullCheckFlag = 1;
                    cbInvoked--;
                    setTimeout(cb, 100);
                    return;
                }

                xhr.responseText = doc.body ? doc.body.innerHTML : null;
                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
                xhr.getResponseHeader = function(header){
                    var headers = {'content-type': opts.dataType};
                    return headers[header];
                };

                if (opts.dataType == 'json' || opts.dataType == 'script') {
                    var ta = doc.getElementsByTagName('textarea')[0];
                    xhr.responseText = ta ? ta.value : xhr.responseText;
                }
                else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
                    xhr.responseXML = toXml(xhr.responseText);
                }
                data = $.httpData(xhr, opts.dataType);
            }
            catch(e){
                ok = false;
                $.handleError(opts, xhr, 'error', e);
            }

            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
            if (ok) {
                opts.success(data, 'success');
                if (g) $.event.trigger("ajaxSuccess", [xhr, opts]);
            }
            if (g) $.event.trigger("ajaxComplete", [xhr, opts]);
            if (g && ! --$.active) $.event.trigger("ajaxStop");
            if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error');

            // clean up
            setTimeout(function() {
                $io.remove();
                xhr.responseXML = null;
            }, 100);
        };

        function toXml(s, doc) {
            if (window.ActiveXObject) {
                doc = new ActiveXObject('Microsoft.XMLDOM');
                doc.async = 'false';
                doc.loadXML(s);
            }
            else
                doc = (new DOMParser()).parseFromString(s, 'text/xml');
            return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
        };
    };
};

/**
 * ajaxForm() provides a mechanism for fully automating form submission.
 *
 * The advantages of using this method instead of ajaxSubmit() are:
 *
 * 1: This method will include coordinates for <input type="image" /> elements (if the element
 *    is used to submit the form).
 * 2. This method will include the submit element's name/value data (for the element that was
 *    used to submit the form).
 * 3. This method binds the submit() method to the form for you.
 *
 * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
 * passes the options argument along after properly binding events for submit elements and
 * the form itself.
 */
$.fn.ajaxForm = function(options) {
    return this.ajaxFormUnbind().bind('submit.form-plugin',function() {
        $(this).ajaxSubmit(options);
        return false;
    }).each(function() {
        // store options in hash
        $(":submit,input:image", this).bind('click.form-plugin',function(e) {
            var form = this.form;
            form.clk = this;
            if (this.type == 'image') {
                if (e.offsetX != undefined) {
                    form.clk_x = e.offsetX;
                    form.clk_y = e.offsetY;
                } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
                    var offset = $(this).offset();
                    form.clk_x = e.pageX - offset.left;
                    form.clk_y = e.pageY - offset.top;
                } else {
                    form.clk_x = e.pageX - this.offsetLeft;
                    form.clk_y = e.pageY - this.offsetTop;
                }
            }
            // clear form vars
            setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 10);
        });
    });
};

// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function() {
    this.unbind('submit.form-plugin');
    return this.each(function() {
        $(":submit,input:image", this).unbind('click.form-plugin');
    });

};

/**
 * formToArray() gathers form element data into an array of objects that can
 * be passed to any of the following ajax functions: $.get, $.post, or load.
 * Each object in the array has both a 'name' and 'value' property.  An example of
 * an array for a simple login form might be:
 *
 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
 *
 * It is this array that is passed to pre-submit callback functions provided to the
 * ajaxSubmit() and ajaxForm() methods.
 */
$.fn.formToArray = function(semantic) {
    var a = [];
    if (this.length == 0) return a;

    var form = this[0];
    var els = semantic ? form.getElementsByTagName('*') : form.elements;
    if (!els) return a;
    for(var i=0, max=els.length; i < max; i++) {
        var el = els[i];
        var n = el.name;
        if (!n) continue;

        if (semantic && form.clk && el.type == "image") {
            // handle image inputs on the fly when semantic == true
            if(!el.disabled && form.clk == el)
                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
            continue;
        }

        var v = $.fieldValue(el, true);
        if (v && v.constructor == Array) {
            for(var j=0, jmax=v.length; j < jmax; j++)
                a.push({name: n, value: v[j]});
        }
        else if (v !== null && typeof v != 'undefined')
            a.push({name: n, value: v});
    }

    if (!semantic && form.clk) {
        // input type=='image' are not found in elements array! handle them here
        var inputs = form.getElementsByTagName("input");
        for(var i=0, max=inputs.length; i < max; i++) {
            var input = inputs[i];
            var n = input.name;
            if(n && !input.disabled && input.type == "image" && form.clk == input)
                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
        }
    }
    return a;
};

/**
 * Serializes form data into a 'submittable' string. This method will return a string
 * in the format: name1=value1&amp;name2=value2
 */
$.fn.formSerialize = function(semantic) {
    //hand off to jQuery.param for proper encoding
    return $.param(this.formToArray(semantic));
};

/**
 * Serializes all field elements in the jQuery object into a query string.
 * This method will return a string in the format: name1=value1&amp;name2=value2
 */
$.fn.fieldSerialize = function(successful) {
    var a = [];
    this.each(function() {
        var n = this.name;
        if (!n) return;
        var v = $.fieldValue(this, successful);
        if (v && v.constructor == Array) {
            for (var i=0,max=v.length; i < max; i++)
                a.push({name: n, value: v[i]});
        }
        else if (v !== null && typeof v != 'undefined')
            a.push({name: this.name, value: v});
    });
    //hand off to jQuery.param for proper encoding
    return $.param(a);
};

/**
 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
 *
 *  <form><fieldset>
 *      <input name="A" type="text" />
 *      <input name="A" type="text" />
 *      <input name="B" type="checkbox" value="B1" />
 *      <input name="B" type="checkbox" value="B2"/>
 *      <input name="C" type="radio" value="C1" />
 *      <input name="C" type="radio" value="C2" />
 *  </fieldset></form>
 *
 *  var v = $(':text').fieldValue();
 *  // if no values are entered into the text inputs
 *  v == ['','']
 *  // if values entered into the text inputs are 'foo' and 'bar'
 *  v == ['foo','bar']
 *
 *  var v = $(':checkbox').fieldValue();
 *  // if neither checkbox is checked
 *  v === undefined
 *  // if both checkboxes are checked
 *  v == ['B1', 'B2']
 *
 *  var v = $(':radio').fieldValue();
 *  // if neither radio is checked
 *  v === undefined
 *  // if first radio is checked
 *  v == ['C1']
 *
 * The successful argument controls whether or not the field element must be 'successful'
 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
 * The default value of the successful argument is true.  If this value is false the value(s)
 * for each element is returned.
 *
 * Note: This method *always* returns an array.  If no valid value can be determined the
 *       array will be empty, otherwise it will contain one or more values.
 */
$.fn.fieldValue = function(successful) {
    for (var val=[], i=0, max=this.length; i < max; i++) {
        var el = this[i];
        var v = $.fieldValue(el, successful);
        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length))
            continue;
        v.constructor == Array ? $.merge(val, v) : val.push(v);
    }
    return val;
};

/**
 * Returns the value of the field element.
 */
$.fieldValue = function(el, successful) {
    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
    if (typeof successful == 'undefined') successful = true;

    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
        (t == 'checkbox' || t == 'radio') && !el.checked ||
        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
        tag == 'select' && el.selectedIndex == -1))
            return null;

    if (tag == 'select') {
        var index = el.selectedIndex;
        if (index < 0) return null;
        var a = [], ops = el.options;
        var one = (t == 'select-one');
        var max = (one ? index+1 : ops.length);
        for(var i=(one ? index : 0); i < max; i++) {
            var op = ops[i];
            if (op.selected) {
				var v = op.value;
				if (!v) // extra pain for IE...
                	v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
                if (one) return v;
                a.push(v);
            }
        }
        return a;
    }
    return el.value;
};

/**
 * Clears the form data.  Takes the following actions on the form's input fields:
 *  - input text fields will have their 'value' property set to the empty string
 *  - select elements will have their 'selectedIndex' property set to -1
 *  - checkbox and radio inputs will have their 'checked' property set to false
 *  - inputs of type submit, button, reset, and hidden will *not* be effected
 *  - button elements will *not* be effected
 */
$.fn.clearForm = function() {
    return this.each(function() {
        $('input,select,textarea', this).clearFields();
    });
};

/**
 * Clears the selected form elements.
 */
$.fn.clearFields = $.fn.clearInputs = function() {
    return this.each(function() {
        var t = this.type, tag = this.tagName.toLowerCase();
        if (t == 'text' || t == 'password' || tag == 'textarea')
            this.value = '';
        else if (t == 'checkbox' || t == 'radio')
            this.checked = false;
        else if (tag == 'select')
            this.selectedIndex = -1;
    });
};

/**
 * Resets the form data.  Causes all form elements to be reset to their original value.
 */
$.fn.resetForm = function() {
    return this.each(function() {
        // guard against an input with the name of 'reset'
        // note that IE reports the reset function as an 'object'
        if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType))
            this.reset();
    });
};

/**
 * Enables or disables any matching elements.
 */
$.fn.enable = function(b) {
    if (b == undefined) b = true;
    return this.each(function() {
        this.disabled = !b;
    });
};

/**
 * Checks/unchecks any matching checkboxes or radio buttons and
 * selects/deselects and matching option elements.
 */
$.fn.selected = function(select) {
    if (select == undefined) select = true;
    return this.each(function() {
        var t = this.type;
        if (t == 'checkbox' || t == 'radio')
            this.checked = select;
        else if (this.tagName.toLowerCase() == 'option') {
            var $sel = $(this).parent('select');
            if (select && $sel[0] && $sel[0].type == 'select-one') {
                // deselect all other options
                $sel.find('option').selected(false);
            }
            this.selected = select;
        }
    });
};

// helper fn for console logging
// set $.fn.ajaxSubmit.debug to true to enable debug logging
function log() {
    if ($.fn.ajaxSubmit.debug && window.console && window.console.log)
        window.console.log('[jquery.form] ' + Array.prototype.join.call(arguments,''));
};

})(jQuery);
$(document).ready(JT_init);
$(document).bind('click', function(e) {
		var $clicked=$(e.target);
		if(!$clicked.is('INPUT[rel=\"jtip\"]') )
		{
			$('#JT').remove();
		} });function JT_init(){
	       $("INPUT[rel=\"jtip\"]")
           .click(function(){$('#JT').remove();JT_show(this.alt,this.id,this.title)});
}function JT_show(content,linkId,title){
	var title="&nbsp;";
	var de = document.documentElement;
	var w = self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
	var hasArea = w - getAbsoluteLeft(linkId);
	var clickElementy = getAbsoluteTop(linkId) - 3; 
	
	var queryString = content.replace(/^[^\?]+\??/,'');
	var params = parseQuery( queryString );
	if(params['width'] === undefined){params['width'] = 200};
	if(params['link'] !== undefined){
	$('#' + linkId).bind('click',function(){window.location = params['link']});
	$('#' + linkId).css('cursor','pointer');
	}
	
	if(hasArea>((params['width']*1)+75)){
		$("body").append("<div id='JT' style='width:"+params['width']*1+"px'><div id='JT_arrow_left'></div><div id='JT_copy'><div class='JT_loader'><div></div></div>");
		var arrowOffset = getElementWidth(linkId) + 11;
		var clickElementx = getAbsoluteLeft(linkId) + arrowOffset; 
	}else{
		$("body").append("<div id='JT' style='width:"+params['width']*1+"px'><div id='JT_arrow_right' style='left:"+((params['width']*1)+1)+"px'></div><div id='JT_copy'><div class='JT_loader'><div></div></div>");
		var clickElementx = getAbsoluteLeft(linkId) - ((params['width']*1) + 15); 
	}
	$('#JT').css({left: clickElementx+"px", top: clickElementy+"px"});
	$('#JT').show();
	$('#JT_copy').append(content); }function getElementWidth(objectId) {
	x = document.getElementById(objectId);
	return x.offsetWidth;
}function getAbsoluteLeft(objectId) {
	
	o = document.getElementById(objectId)
	oLeft = o.offsetLeft            
	while(o.offsetParent!=null) {   
		oParent = o.offsetParent    
		oLeft += oParent.offsetLeft 
		o = oParent
	}
	return oLeft
}function getAbsoluteTop(objectId) {
	
	o = document.getElementById(objectId)
	oTop = o.offsetTop            
	while(o.offsetParent!=null) { 
		oParent = o.offsetParent  
		oTop += oParent.offsetTop 
		o = oParent
	}
	return oTop
}function parseQuery ( query ) {
   var Params = new Object ();
   if ( ! query ) return Params; 
   var Pairs = query.split(/[;&]/);
   for ( var i = 0; i < Pairs.length; i++ ) {
      var KeyVal = Pairs[i].split('=');
      if ( ! KeyVal || KeyVal.length != 2 ) continue;
      var key = unescape( KeyVal[0] );
      var val = unescape( KeyVal[1] );
      val = val.replace(/\+/g, ' ');
      Params[key] = val;
   }
   return Params;
}function blockEvents(evt) {
              if(evt.target){
              evt.preventDefault();
              }else{
              evt.returnValue = false;
              }
}(function($) {
	var pasteEventName = ($.browser.msie ? 'paste' : 'input') + ".mask";
	var iPhone = (window.orientation != undefined);

	$.mask = {
		
		definitions: {
			'9': "[0-9]",
			'a': "[A-Za-z]",
			'*': "[A-Za-z0-9]"
		}
	};

	$.fn.extend({
		
		caret: function(begin, end) {
			if (this.length == 0) return;
			if (typeof begin == 'number') {
				end = (typeof end == 'number') ? end : begin;
				return this.each(function() {
					if (this.setSelectionRange) {
						this.focus();
						this.setSelectionRange(begin, end);
					} else if (this.createTextRange) {
						var range = this.createTextRange();
						range.collapse(true);
						range.moveEnd('character', end);
						range.moveStart('character', begin);
						range.select();
					}
				});
			} else {
				if (this[0].setSelectionRange) {
					begin = this[0].selectionStart;
					end = this[0].selectionEnd;
				} else if (document.selection && document.selection.createRange) {
					var range = document.selection.createRange();
					begin = 0 - range.duplicate().moveStart('character', -100000);
					end = begin + range.text.length;
				}
				return { begin: begin, end: end };
			}
		},
		unmask: function() { return this.trigger("unmask"); },
		mask: function(mask, settings) {
			if (!mask && this.length > 0) {
				var input = $(this[0]);
				var tests = input.data("tests");
				return $.map(input.data("buffer"), function(c, i) {
					return tests[i] ? c : null;
				}).join('');
			}
			settings = $.extend({
				placeholder: "_",
				completed: null
			}, settings);

			var defs = $.mask.definitions;
			var tests = [];
			var partialPosition = mask.length;
			var firstNonMaskPos = null;
			var len = mask.length;

			$.each(mask.split(""), function(i, c) {
				if (c == '?') {
					len--;
					partialPosition = i;
				} else if (defs[c]) {
					tests.push(new RegExp(defs[c]));
					if(firstNonMaskPos==null)
						firstNonMaskPos =  tests.length - 1;
				} else {
					tests.push(null);
				}
			});

			return this.each(function() {
				var input = $(this);
				var buffer = $.map(mask.split(""), function(c, i) { if (c != '?') return defs[c] ? settings.placeholder : c });
				var ignore = false;  			
				var focusText = input.val();

				input.data("buffer", buffer).data("tests", tests);

				function seekNext(pos) {
					while (++pos <= len && !tests[pos]);
					return pos;
				};

				function shiftL(pos) {
					while (!tests[pos] && --pos >= 0);
					for (var i = pos; i < len; i++) {
						if (tests[i]) {
							buffer[i] = settings.placeholder;
							var j = seekNext(i);
							if (j < len && tests[i].test(buffer[j])) {
								buffer[i] = buffer[j];
							} else
								break;
						}
					}
					writeBuffer();
					input.caret(Math.max(firstNonMaskPos, pos));
				};

				function shiftR(pos) {
					for (var i = pos, c = settings.placeholder; i < len; i++) {
						if (tests[i]) {
							var j = seekNext(i);
							var t = buffer[i];
							buffer[i] = c;
							if (j < len && tests[j].test(t))
								c = t;
							else
								break;
						}
					}
				};

				function keydownEvent(e) {
					var pos = $(this).caret();
					var k = e.keyCode;
					ignore = (k < 16 || (k > 16 && k < 32) || (k > 32 && k < 41));

					
					if ((pos.begin - pos.end) != 0 && (!ignore || k == 8 || k == 46))
						clearBuffer(pos.begin, pos.end);

					
					if (k == 8 || k == 46 || (iPhone && k == 127)) {
						shiftL(pos.begin + (k == 46 ? 0 : -1));
						return false;
					} else if (k == 27) {
						input.val(focusText);
						input.caret(0, checkVal());
						return false;
					}
				};

				function keypressEvent(e) {
					if (ignore) {
						ignore = false;
						
						return (e.keyCode == 8) ? false : null;
					}
					e = e || window.event;
					var k = e.charCode || e.keyCode || e.which;
					var pos = $(this).caret();

					if (e.ctrlKey || e.altKey || e.metaKey) {
						return true;
					} else if ((k >= 32 && k <= 125) || k > 186) {
						var p = seekNext(pos.begin - 1);
						if (p < len) {
							var c = String.fromCharCode(k);
							if (tests[p].test(c)) {
								shiftR(p);
								buffer[p] = c;
								writeBuffer();
								var next = seekNext(p);
								$(this).caret(next);
								if (settings.completed && next == len)
									settings.completed.call(input);
							}
						}
					}
					return false;
				};

				function clearBuffer(start, end) {
					for (var i = start; i < end && i < len; i++) {
						if (tests[i])
							buffer[i] = settings.placeholder;
					}
				};

				function writeBuffer() { return input.val(buffer.join('')).val(); };

				function checkVal(allow) {
					
					var test = input.val();
					var lastMatch = -1;
					for (var i = 0, pos = 0; i < len; i++) {
						if (tests[i]) {
							buffer[i] = settings.placeholder;
							while (pos++ < test.length) {
								var c = test.charAt(pos - 1);
								if (tests[i].test(c)) {
									buffer[i] = c;
									lastMatch = i;
									break;
								}
							}
							if (pos > test.length)
								break;
						} else if (buffer[i] == test[pos] && i!=partialPosition) {
							pos++;
							lastMatch = i;
						} 
					}
					if (!allow && lastMatch + 1 < partialPosition) {
						input.val("");
						clearBuffer(0, len);
					} else if (allow || lastMatch + 1 >= partialPosition) {
						writeBuffer();
						if (!allow) input.val(input.val().substring(0, lastMatch + 1));
					}
					return (partialPosition ? i : firstNonMaskPos);
				};

				if (!input.attr("readonly"))
					input
					.one("unmask", function() {
						input
							.unbind(".mask")
							.removeData("buffer")
							.removeData("tests");
					})
					.bind("focus.mask", function() {
						focusText = input.val();
						var pos = checkVal();
						writeBuffer();
						setTimeout(function() {
							if (pos == mask.length)
								input.caret(0, pos);
							else
								input.caret(pos);
						}, 0);
					})
					.bind("blur.mask", function() {
						checkVal();
						if (input.val() != focusText)
							input.change();
					})
					.bind("keydown.mask", keydownEvent)
					.bind("keypress.mask", keypressEvent)
					.bind(pasteEventName, function() {
						setTimeout(function() { input.caret(checkVal(true)); }, 0);
					});

				checkVal(); 
			});
		}
	});
})(jQuery);function advAJAX(){var obj=new Object();obj.url=window.location.href;obj.method="GET";obj.parameters=new Object();obj.jsonParameters=new Object();obj.headers=new Object();obj.async=true;obj.mimeType="text/xml";obj.username=null;obj.password=null;obj.form=null;obj.disableForm=true;obj.unique=true;obj.uniqueParameter="_uniqid";obj.requestDone=false;obj.queryString="";obj.responseText=null;obj.responseXML=null;obj.status=null;obj.statusText=null;obj.aborted=false;obj.timeout=0;obj.retryCount=0;obj.retryDelay=1000;obj.tag=null;obj.group=null;obj.progressTimerInterval=50;obj.xmlHttpRequest=null;obj.onInitialization=null;obj.onFinalization=null;obj.onReadyStateChange=null;obj.onLoading=null;obj.onLoaded=null;obj.onInteractive=null;obj.onComplete=null;obj.onProgress=null;obj.onSuccess=null;obj.onFatalError=null;obj.onError=null;obj.onTimeout=null;obj.onRetryDelay=null;obj.onRetry=null;obj.onGroupEnter=null;obj.onGroupLeave=null;obj.createXmlHttpRequest=function(){if(typeof XMLHttpRequest!="undefined"){return new XMLHttpRequest();}var xhrVersion=["MSXML2.XMLHttp.5.0","MSXML2.XMLHttp.4.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp","Microsoft.XMLHttp"];for(var i=0;i<xhrVersion.length;i++){try{var xhrObj=new ActiveXObject(xhrVersion[i]);return xhrObj;}catch(e){}}obj.raiseEvent("FatalError");return null;};obj._oldResponseLength=null;obj._progressTimer=null;obj._progressStarted=navigator.userAgent.indexOf("Opera")==-1;obj._onProgress=function(){if(typeof obj.onProgress=="function"&&typeof obj.xmlHttpRequest.getResponseHeader=="function"){var contentLength=obj.xmlHttpRequest.getResponseHeader("Content-length");if(contentLength!=null&&contentLength!=""){var responseLength=obj.xmlHttpRequest.responseText.length;if(responseLength!=obj._oldResponseLength){obj.raiseEvent("Progress",obj,responseLength,contentLength);obj._oldResponseLength=obj.xmlHttpRequest.responseText.length;}}}if(obj._progressStarted){return ;}obj._progressStarted=true;var _obj=this;this.__onProgress=function(){obj._onProgress();obj._progressTimer=window.setTimeout(_obj.__onProgress,obj.progressTimerInterval);};_obj.__onProgress();};obj._onInitializationHandled=false;obj._initObject=function(){if(obj.xmlHttpRequest!=null){delete obj.xmlHttpRequest.onreadystatechange;obj.xmlHttpRequest=null;}if((obj.xmlHttpRequest=obj.createXmlHttpRequest())==null){return null;}if(typeof obj.xmlHttpRequest.overrideMimeType!="undefined"){obj.xmlHttpRequest.overrideMimeType(obj.mimeType);}obj.xmlHttpRequest.onreadystatechange=function(){if(obj==null||obj.xmlHttpRequest==null){return ;}obj.raiseEvent("ReadyStateChange",obj,obj.xmlHttpRequest.readyState);obj._onProgress();switch(obj.xmlHttpRequest.readyState){case 1:obj._onLoading();break;case 2:obj._onLoaded();break;case 3:obj._onInteractive();break;case 4:obj._onComplete();break;}};obj._onLoadingHandled=obj._onLoadedHandled=obj._onInteractiveHandled=obj._onCompleteHandled=false;};obj._onLoading=function(){if(obj._onLoadingHandled){return ;}if(!obj._retry&&obj.group!=null){if(typeof advAJAX._groupData[obj.group]=="undefined"){advAJAX._groupData[obj.group]=0;}advAJAX._groupData[obj.group]++;if(typeof obj.onGroupEnter=="function"&&advAJAX._groupData[obj.group]==1){obj.onGroupEnter(obj);}}obj.raiseEvent("Loading",obj);obj._onLoadingHandled=true;};obj._onLoaded=function(){if(obj._onLoadedHandled){return ;}obj.raiseEvent("Loaded",obj);obj._onLoadedHandled=true;};obj._onInteractive=function(){if(obj._onInteractiveHandled){return ;}obj.raiseEvent("Interactive",obj);obj._onInteractiveHandled=true;if(!obj._progressStarted){obj._onProgress();}};obj._onComplete=function(){if(obj._onCompleteHandled||obj.aborted){return ;}if(obj._progressStarted){window.clearInterval(obj._progressTimer);obj._progressStarted=false;}obj.requestDone=true;with(obj.xmlHttpRequest){obj.responseText=responseText;obj.responseXML=responseXML;if(typeof status!="undefined"){obj.status=status;}if(typeof statusText!="undefined"){obj.statusText=statusText;}}obj.raiseEvent("Complete",obj);obj._onCompleteHandled=true;if(obj.status==200){obj.raiseEvent("Success",obj);}else{obj.raiseEvent("Error",obj);}delete obj.xmlHttpRequest.onreadystatechange;obj.xmlHttpRequest=null;if(obj.disableForm){obj.switchForm(true);}obj._groupLeave();obj.raiseEvent("Finalization",obj);};obj._groupLeave=function(){if(obj.group!=null){advAJAX._groupData[obj.group]--;if(advAJAX._groupData[obj.group]==0){obj.raiseEvent("GroupLeave",obj);}}};obj._retry=false;obj._retryNo=0;obj._onTimeout=function(){if(obj==null||obj.xmlHttpRequest==null||obj._onCompleteHandled){return ;}obj.aborted=true;obj.xmlHttpRequest.abort();obj.raiseEvent("Timeout",obj);obj._retry=true;if(obj._retryNo!=obj.retryCount){obj._initObject();if(obj.retryDelay>0){obj.raiseEvent("RetryDelay",obj);startTime=new Date().getTime();while(new Date().getTime()-startTime<obj.retryDelay){}}obj._retryNo++;obj.raiseEvent("Retry",obj,obj._retryNo);obj.run();}else{delete obj.xmlHttpRequest.onreadystatechange;obj.xmlHttpRequest=null;if(obj.disableForm){obj.switchForm(true);}obj._groupLeave();obj.raiseEvent("Finalization",obj);}};obj.run=function(){obj._initObject();if(obj.xmlHttpRequest==null){return false;}obj.aborted=false;if(!obj._onInitializationHandled){obj.raiseEvent("Initialization",obj);obj._onInitializationHandled=true;}if(obj.method=="GET"&&obj.unique){obj.parameters[encodeURIComponent(obj.uniqueParameter)]=new Date().getTime().toString().substr(5)+Math.floor(Math.random()*100).toString();}if(!obj._retry){for(var a in obj.parameters){if(obj.queryString.length>0){obj.queryString+="&";}if(typeof obj.parameters[a]!="object"){obj.queryString+=encodeURIComponent(a)+"="+encodeURIComponent(obj.parameters[a]);}else{for(var i=0;i<obj.parameters[a].length;i++){obj.queryString+=encodeURIComponent(a)+"="+encodeURIComponent(obj.parameters[a][i])+"&";}obj.queryString=obj.queryString.slice(0,-1);}}for(var a in obj.jsonParameters){var useJson=typeof [].toJSONString=="function";if(obj.queryString.length>0){obj.queryString+="&";}obj.queryString+=encodeURIComponent(a)+"=";if(useJson){obj.queryString+=encodeURIComponent(obj.jsonParameters[a].toJSONString());}else{obj.queryString+=encodeURIComponent(obj.jsonParameters[a]);}}if(obj.method=="GET"&&obj.queryString.length>0){obj.url+=(obj.url.indexOf("?")!=-1?"&":"?")+obj.queryString;}}if(obj.disableForm){obj.switchForm(false);}try{obj.xmlHttpRequest.open(obj.method,obj.url,obj.async,obj.username||"",obj.password||"");}catch(e){obj.raiseEvent("FatalError",obj,e);return ;}if(obj.timeout>0){setTimeout(obj._onTimeout,obj.timeout);}if(typeof obj.xmlHttpRequest.setRequestHeader!="undefined"){for(var a in obj.headers){obj.xmlHttpRequest.setRequestHeader(encodeURIComponent(a),encodeURIComponent(obj.headers[a]));}}if(obj.method=="POST"&&typeof obj.xmlHttpRequest.setRequestHeader!="undefined"){obj.xmlHttpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");obj.xmlHttpRequest.send(obj.queryString);}else{if(obj.method=="GET"){obj.xmlHttpRequest.send("");}}};obj.handleArguments=function(args){if(typeof args.form=="object"&&args.form!=null){obj.form=args.form;obj.appendForm();}for(a in args){if(typeof obj[a]=="undefined"){obj.parameters[a]=args[a];}else{if(a!="parameters"&&a!="headers"){obj[a]=args[a];}else{for(b in args[a]){obj[a][b]=args[a][b];}}}}obj.method=obj.method.toUpperCase();};obj.switchForm=function(enable){if(typeof obj.form!="object"||obj.form==null){return ;}with(obj.form){for(var nr=0;nr<elements.length;nr++){if(!enable){if(elements[nr]["disabled"]){elements[nr]["_disabled"]=true;}else{elements[nr]["disabled"]="disabled";}}else{if(typeof elements[nr]["_disabled"]=="undefined"){elements[nr].removeAttribute("disabled");}}}}};obj.appendForm=function(){with(obj.form){obj.method=getAttribute("method").toUpperCase();obj.url=getAttribute("action");for(var nr=0;nr<elements.length;nr++){var e=elements[nr];if(e.disabled){continue;}switch(e.type){case"text":case"password":case"hidden":case"textarea":obj.addParameter(e.name,e.value);break;case"select-one":if(e.selectedIndex>=0){obj.addParameter(e.name,e.options[e.selectedIndex].value);}break;case"select-multiple":for(var nr2=0;nr2<e.options.length;nr2++){if(e.options[nr2].selected){obj.addParameter(e.name,e.options[nr2].value);}}break;case"checkbox":case"radio":if(e.checked){obj.addParameter(e.name,e.value);}break;}}}};obj.addParameter=function(name,value){if(typeof obj.parameters[name]=="undefined"){obj.parameters[name]=value;}else{if(typeof obj.parameters[name]!="object"){obj.parameters[name]=[obj.parameters[name],value];}else{obj.parameters[name][obj.parameters[name].length]=value;}}};obj.delParameter=function(name){delete obj.parameters[name];};obj.raiseEvent=function(name){var args=[];for(var i=1;i<arguments.length;i++){args.push(arguments[i]);}if(typeof obj["on"+name]=="function"){obj["on"+name].apply(null,args);}if(name=="FatalError"){obj.raiseEvent("Finalization",obj);}};if(typeof advAJAX._defaultParameters!="undefined"){obj.handleArguments(advAJAX._defaultParameters);}return obj;}advAJAX.get=function(A){return advAJAX.handleRequest("GET",A);};advAJAX.post=function(A){return advAJAX.handleRequest("POST",A);};advAJAX.head=function(A){return advAJAX.handleRequest("HEAD",A);};advAJAX.submit=function(C,A){if(typeof A=="undefined"||A==null){return -1;}if(typeof C!="object"||C==null){return -2;}var B=new advAJAX();A.form=C;B.handleArguments(A);return B.run();};advAJAX.assign=function(B,A){if(typeof A=="undefined"||A==null){return -1;}if(typeof B!="object"||B==null){return -2;}if(typeof B.onsubmit=="function"){B._onsubmit=B.onsubmit;}B.advajax_args=A;B.onsubmit=function(){if(typeof this["_onsubmit"]!="undefined"&&this["_onsubmit"]()===false){return false;}if(advAJAX.submit(this,this["advajax_args"])==false){return true;}return false;};return true;};advAJAX.download=function(B,A){if(typeof B=="string"){B=document.getElementById(B);}if(!B){return -1;}advAJAX.get({url:A,onSuccess:function(C){B.innerHTML=C.responseText;}});};advAJAX.scan=function(){var D=document.getElementsByTagName("a");for(var B=0;B<D.length;){if(D[B].getAttribute("rel")=="advancedajax"&&D[B].getAttribute("href")!==null){var A=D[B].getAttribute("href");var E=document.createElement("div");E.innerHTML=D[B].innerHTML;E.className=D[B].className;var C=D[B].parentNode;C.insertBefore(E,D[B]);C.removeChild(D[B]);advAJAX.download(E,A);}else{B++;}}};advAJAX.handleRequest=function(A,B){if(typeof B=="undefined"||B==null){return -1;}var C=new advAJAX();window.advajax_obj=C;C.method=A;C.handleArguments(B);return C.run();};advAJAX._defaultParameters=new Object();advAJAX.setDefaultParameters=function(A){advAJAX._defaultParameters=new Object();for(a in A){advAJAX._defaultParameters[a]=A[a];}};advAJAX._groupData=new Object();
Array.prototype.removeDuplicates=function(){for(var A=1;A<this.length;A++){if(this[A][0]==this[A-1][0]){this.splice(A,1)}}};Array.prototype.empty=function(){for(var A=0;A<=this.length;A++){this.shift()}};String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")};function LyteBox(){this.theme="grey";this.hideFlash=true;this.outerBorder=true;this.resizeSpeed=8;this.maxOpacity=80;this.navType=1;this.autoResize=true;this.doAnimations=true;this.borderSize=12;this.slideInterval=4000;this.showNavigation=true;this.showClose=true;this.showDetails=true;this.showPlayPause=true;this.autoEnd=true;this.pauseOnNextClick=false;this.pauseOnPrevClick=true;if(this.resizeSpeed>10){this.resizeSpeed=10}if(this.resizeSpeed<1){resizeSpeed=1}this.resizeDuration=(11-this.resizeSpeed)*0.15;this.resizeWTimerArray=new Array();this.resizeWTimerCount=0;this.resizeHTimerArray=new Array();this.resizeHTimerCount=0;this.showContentTimerArray=new Array();this.showContentTimerCount=0;this.overlayTimerArray=new Array();this.overlayTimerCount=0;this.imageTimerArray=new Array();this.imageTimerCount=0;this.timerIDArray=new Array();this.timerIDCount=0;this.slideshowIDArray=new Array();this.slideshowIDCount=0;this.imageArray=new Array();this.activeImage=null;this.slideArray=new Array();this.activeSlide=null;this.frameArray=new Array();this.activeFrame=null;this.checkFrame();this.isSlideshow=false;this.isLyteframe=false;}
if (!this.JSON) {
JSON = {};
}
(function () {

function f(n) {
return n < 10 ? '0' + n : n;
}

if (typeof Date.prototype.toJSON !== 'function') {

Date.prototype.toJSON = function (key) {

return this.getUTCFullYear()   + '-' +
 f(this.getUTCMonth() + 1) + '-' +
 f(this.getUTCDate())  + 'T' +
 f(this.getUTCHours()) + ':' +
 f(this.getUTCMinutes())   + ':' +
 f(this.getUTCSeconds())   + 'Z';
};

String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function (key) {
return this.valueOf();
};
}

var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { 
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep;function quote(string) {
escapeable.lastIndex = 0;
return escapeable.test(string) ?
'"' + string.replace(escapeable, function (a) {
var c = meta[a];
if (typeof c === 'string') {
return c;
}
return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' :
'"' + string + '"';
}function str(key, holder) {
var i,
k, 
v, 
length,
mind = gap,
partial,
value = holder[key];
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}

if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
switch (typeof value) {
case 'string':
return quote(value);

case 'number':
return isFinite(value) ? String(value) : 'null';

case 'boolean':
case 'null':

return String(value);
case 'object':

if (!value) {
return 'null';
}gap += indent;
partial = [];if (typeof value.length === 'number' &&
!value.propertyIsEnumerable('length')) {
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
v = partial.length === 0 ? '[]' :
gap ? '[\n' + gap +
partial.join(',\n' + gap) + '\n' +
mind + ']' :
  '[' + partial.join(',') + ']';
gap = mind;
return v;
}if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
k = rep[i];
if (typeof k === 'string') {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
v = partial.length === 0 ? '{}' :
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
mind + '}' : '{' + partial.join(',') + '}';
gap = mind;
return v;
}
}if (typeof JSON.stringify !== 'function') {
JSON.stringify = function (value, replacer, space) {var i;
gap = '';
indent = '';
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}} else if (typeof space === 'string') {
indent = space;
}
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
 typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
return str('', {'': value});
};
}
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
var j;

function walk(holder, key) {
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {j = eval('(' + text + ')');
return typeof reviver === 'function' ?
walk({'': j}, '') : j;
}throw new SyntaxError('JSON.parse');
};
}
})();
/* related to jcarousel logic */

/**
 *
 * @access public
 * @return void
 **/

function cc_getPos(name, params){
	first = readCookie(name+':'+JSON.stringify(params));
	if(first==null) return 1;
	return parseInt(first);
}

function cc_move(carousel, item, position, state){
	if(state=='prev' || state=='next')
	createCookie(carousel.options.name + ':' + JSON.stringify(carousel.options.params), position);
}

function cc_getItems(carousel)
{
}

function get_cc_submit()
{
	return function(){
		return cc_submit.apply(this, arguments);
	}
}

/**
 *
 * @access public
 * @return void
 **/
function shuffle( inputArr ) {
    inputArr.sort(function() {return 0.5 - Math.random();});
    return true;
}
function cc_init(carousel, state)
{
	if((state=='reset') || (state=='init'))
	{
		$.getJSON("/carousel-" + carousel.options.name + ".html", carousel.options.params, function(result){
			if(result=='{}') result='[]';
			carousel.options.cloths = eval(result);
			if(carousel.options.special == 'sponsor') { shuffle(carousel.options.cloths); }
			carousel.options.size = carousel.options.cloths.length;
			carousel.scroll(cc_getPos(carousel.options.name, carousel.options.params),false);
			cc_load(carousel, 'ajax');
		});
		jQuery('.wieszak_delete', carousel.container).livequery('click', function(e){
			deleteFav(this, $(this).attr('id'), carousel);
			e.preventDefault();
			e.stopPropagation();
			return false;
		});
	}
	return true;
};


function cc_load(carousel, state)
{
	if(state=='init') return true;
	if(carousel.options.cloths.length > 0)
	{
	    for (var i = carousel.first; i <= carousel.last; i++) {
            carousel.add(i, carousel.options.cloths[i-1]);
	    }
	}
	return true;
};

function deleteFav(btn, cid, carousel){
	$.get('/favDel-cloth.html',{id: cid}, function(data){
		if(data=='1')
		{
			carousel.reset();
			msgBox('Przedmiot został usunięty z ulubionych', 1);
		}
		else
		{
			msgBox('Przedmiot nie został usunięty z ulubionych', 0);
		}
	}, 'text');
}try {
    if (top != self) top.location.href = location.href;
} catch (e) {};

function sug_vote(type, sug_id){
    if(confirm("Czy na pewno chcesz zagłosować na tę sugestię?")){
        $.post("/ajax-sugVote.html", {
            sug_type:type,
            sug_id:sug_id
        },
        function(returned_data)
        {
            alert(returned_data);
            location.href=location.href;
            window.location.href=window.location.href;
        });
        return true;
    }else{
        return false;
    }
}

function checkDiscountCode(){
    var form = document.kupon_checker;

    if(form.discount_code.value==""){
        alert("Proszę wpisać kod promocyjny.");
        return false;
    }

    $("#kupon-container-1").fadeOut('fast');
    $("#kupon-container-loader").fadeIn('fast');

    $.post("/ajax-checkDcode.html", {
        code: form.discount_code.value
    },
    function(data) {
        $("#kupon-container-loader").fadeOut('fast');
        $("#kupon-container-2").html(data);
        $("#kupon-container-2").fadeIn('fast');
    });

    return false;
}

function add_sug_com(){
    var form = document.addsugcom;

    if(form.sug_com.value==""){
        alert('Proszę uzupełnić treść komentarza.');
        return false;
    }
    if(form.sug_com.value.length<20){
        alert('Twój komentarz musi mieć conajmniej 20 znaków.');
        return false;
    }

    return true;
}

function add_sug(){
    var form = document.addsug;

    if(form.sug_title.value==""){
        alert('Proszę uzupełnić pole tytuł sugestii.');
        return false;
    }
    if(form.sug_title.value.length<20){
        alert('Tytuł sugestii musi mieć conajmniej 20 znaków.');
        return false;
    }
    if(form.sug_desc.value==""){
        alert('Proszę uzupełnić pole opis sugestii.');
        return false;
    }
    if(form.sug_desc.value.length<50){
        alert('Proszę dokładniej opisać sugestię.');
        return false;
    }

    return true;

}

function phonefield(event)
{
    if (event.srcElement) {
        kc = event.keyCode;
    } else {
        kc = event.which;
    }
    if ((kc < 48 || kc > 57) && (kc < 0 || kc > 32) && kc != 40 && kc != 41 && kc != 45 && kc != 43 && kc != 8 && kc != 127 && kc != 0) return false;
    return true;
}
	
	
function showOtherCats(){
    $('.collapsed').attr('style','display: block');
    $('#cats-arrow').attr('style','display: none');
    $('#cats-arrow-down').attr('style','display: none');
}
	
// Cienie dla tekstów
jQuery.fn.textShadow = function () {
    return this.each(function () {
        var el = $(this);

        el.html('<span class="jquery-text-shadow-text">' + el.html() + '</span>').css('position', 'relative');
        jQuery('<span class="jquery-text-shadow">' + el.html() + '</span>').appendTo(el);
    });
};
	
// Cienie dla tekstów
jQuery.fn.textShadow2 = function () {
    return this.each(function () {
        var el = $(this);

        el.html('<span class="jquery-text-shadow-text2">' + el.html() + '</span>').css('position', 'relative');
        jQuery('<span class="jquery-text-shadow2">' + el.html() + '</span>').appendTo(el);
    });
};
	
// Toggle z fadingiem
jQuery.fn.fadeToggle = function(speed, easing, callback) { 
    return this.animate({
        opacity: 'toggle'
    }, speed, easing, callback);
};
	

// mode : 0 - error, 1 - ok
$(document).ready(function(){
    $("#abuse_box .close_btn").bind("click", function(){
        $("#abuse_box").fadeOut("slow");
        $("#c_report_abuse_button").show();
    });

	$('a#sugestie-tip').tooltip({
		showURL: false
	});
	
    $('.helper_text').bt({
        trigger: ['click'],
        positions: ['right'],
        width: '400px',
        shrinkToFit: true
    });

    //modyfikacja ustawien, to by chyba trzeba gdzies wyjebac razem z tym co jest wyzej
    var toggleMinus = 'Nie zmieniaj hasła';
    var togglePlus = 'Zmiana hasła';
    var $LinkC = $('#ajax_hasla > a');
    var toggleSrc = togglePlus;
    var imgAv = $('div#aboutMeAvatar a.bigAvatar');
    imgAv.preload();
    imgAv.flyout();
    $('a.imgShow').livequery(function(){
        $(this).flyout();
    });

    $('#ajax_hasla > a').click(function() {

        if ( toggleSrc == toggleMinus ) {
            $LinkC.text(togglePlus);
            toggleSrc=togglePlus;
            $('#ajax_hasla_p1').fadeOut('slow');
            $('#ajax_hasla_p2').fadeOut('slow');
            $('#ajax_hasla_p3').fadeOut('slow');

        } else{
            $LinkC.text(toggleMinus);
            toggleSrc=toggleMinus;
            $('#ajax_hasla_p1').fadeIn('slow');
            $('#ajax_hasla_p2').fadeIn('slow');
            $('#ajax_hasla_p3').fadeIn('slow');
        };
    });
    $('.nodef').click(function(e){
        e.preventDefault();
    });
    $('.stopProp').click(function(e){
        e.stopPropagation();
    });
    $('.ajaxGet').click(function(e){
        e.preventDefault();
        var it = $(this);
        var q = it.attr('title');
        if(q!=undefined){
            if(!confirm(q)) return false;
        }
        jQuery.get(it.attr('href'), {}, function(data, textStatus){
            if(data=='1') it.parents('tr').remove();
        }, 'text');
        return false;
    });
    $('#abuse_btn').click(function(e){
        reportAbuse($('#c_abuse_form').attr('action'), $('#abuse_type').val(), $('#abuse_id').val(), $('#abuse_reason').val(), '#abuse_div')
        $('#abuse_box').fadeOut("fast");
        return false;
    });
    jQuery('#showWidgetPreview').click(function(e){
        if(jQuery('#widgetPreview').toggle().is(':visible'))
        {
            jQuery('#showWidgetPreview').html('Ukryj banner');
        }
        else
        {
            jQuery('#showWidgetPreview').html('Podgląd bannera');
        }
        return false;
    });

    $('#ec_page_name').textShadow2();


    var mb = jQuery('#messageBox');
    mb.fadeOut();
});

function acceptVerification(id){
    if(confirm("Ar Ju Wsiur?")){
        $.get("ajax-AdminAcceptVerify.html",
        {
            uid:id,
            status: 3
        },
        function(returned_data)
        {
            //alert(returned_data);
            if(returned_data=='Status został zmieniony :-)'){
				    
            }else{
                alert(returned_data);
            }
        });
        document.getElementById('id_'+id).style.display='none';
        return true;
    }else{
        return false;
    }
}

function acceptVerification2(id, mode){
    if(confirm("Ar Ju Wsiur?")){
        $.get("ajax-AdminAcceptVerify.html",
        {
            uid:id,
            status:mode
        },
        function(returned_data)
        {
            //alert(returned_data);
            if(returned_data=='Status został zmieniony :-)'){
            }else{
                alert(returned_data);
            }
        });
        document.getElementById('ww_id_'+id).style.display='none';
        return true;
    }else{
        return false;
    }
}

function closeMailer(){
    jQuery('#fancy_close').click();
}

function msgBox(message, mode, url, where){
    //var mb =
    jQuery(where==undefined?'body':where).jAlert(message, mode?'success':'fatal');
    if(url!=undefined && url!='')
    {
        setTimeout("document.location = '" + url + "';", 4000);
    }
}

function usun_przedmiot(id){
    if(confirm('Czy napewno chcesz usunąć ten przedmiot?'))
    {
        jQuery.get('/usun_przedmiot,'+id+'.html',function(data){
            if(data=='1')
            {
                msgBox('Przedmiot został usunięty',1, '/profil.html');
            }
            else
            {
                msgBox('Przedmiot nie został usunięty',0);
            }
        });
    }
    return false;
}
function przenies_przedmiot(id){
    if(confirm('Czy napewno chcesz przenieść ten przedmiot?'))
    {
        jQuery.get('/ajax-functions.html?action=move_cloth&id='+id,function(data){
            if(data=='1')
            {
                msgBox('Przedmiot został przeniesiony',1, '/profil.html');
            }
            else
            {
                msgBox('Przedmiot nie został przeniesiony',0);
            }
        });
    }
    return false;
}


function reportAbuse(type,id){
    if(confirm('Czy napewno chcesz zgłosić nieprawidłowość?'))
    {
        jQuery.get('/ajax/abuse,'+type+','+id+'.html',function(data){
            if(data=='1')
            {
                msgBox('Nieprawidłowość została zgłoszona, dziękujemy.',1);
            }
            else
            {
                msgBox('Wystąpił błąd przy zgłaszaniu nieprawidłowości.',0);
            }
        });
    }
    return false;
}

function generateCWidget(type,id,bbcodeDiv){
    jQuery.get('/ajax/createWidget.php?type='+type+'&cid='+id,function(data){
        if(data=='0')
        {
            msgBox('Wystąpił problem podczas generownia kodu',1);
        }
        else
        {
            jQuery('#genBBCodeWidget').hide();
            jQuery('#'+bbcodeDiv+'In').val(data);
            jQuery('#'+bbcodeDiv).show();
        }
    });
    return false;
}

// Obsługa boxa z powiadomieniami
function show_prompt_box(name, text, fnc, args){
    isIE6 = /msie|MSIE 6/.test(navigator.userAgent);
    isIE = /msie|MSIE/.test(navigator.userAgent);
    $("#prompt_box2 .container .prompt_name").text(name);
    $("#prompt_box2 .container .prompt_text").html(text);
    var hide = $("#prompt_hide");
    if(fnc!=undefined){
        hide.css('display: block');
        hide.unbind('click');
        hide.click(function(){
            fnc.apply({}, args)
            });
    } else {
        hide.css('display: none');
    }
    if(isIE){
        $("#prompt_box2").fadeIn("slow");
    }else{
        $("#prompt_box2").fadeIn("slow");
    }
}



function softdel(id, uid, redirect, toHide){
    if(redirect==undefined) redirect='/index.html';
    var form = '<div style="line-height: 200%;"><input type="checkbox" id="powod1" name="powod1" value="Zła kategoria przedmiotu"/> Zła kategoria przedmiotu<br/><input type="checkbox" id="powod2" name="powod2" value="Niedozwolona forma sprzedaży - licytacja"/> Niedozwolona forma sprzedaży - licytacja<br/><input type="checkbox" id="powod3" name="powod3" value="Niedozwolona sprzedaż - konto niezweryfikowane"/> Niedozwolona sprzedaż - konto niezweryfikowane<br/><input type="checkbox" id="powod4" name="powod4" value="Przedmiot niezgodny z tematyką serwisu"/> Przedmiot niezgodny z tematyką serwisu<br/><input type="checkbox" id="powod5" name="powod5" value="Przedmiot narusza Regulamin Szafka.pl"/> Przedmiot narusza Regulamin Szafka.pl  (np. podróbki)<br/>Inny powód <input type="text" id="powod6" name="powod6" value=""/></div>';
    show_prompt_box("Pytanie", form, softdelhelper, [id, uid, redirect, toHide]);
    return false;
}

function softdelhelper(id, uid, redirect, toHide){
    var powod1 = $("#powod1");
    var powod2 = $("#powod2");
    var powod3 = $("#powod3");
    var powod4 = $("#powod4");
    var powod5 = $("#powod5");
    var powod6 = $("#powod6");
    if(powod1.attr("checked") || powod2.attr("checked") || powod3.attr("checked") || powod4.attr("checked") || powod5.attr("checked") || powod6.val()!="")
    {
        powody = new Array();
        if(powod1.attr("checked")){
            powody[0] = powod1.val();
        }else{
            powody[0] = '';
        }
        if(powod2.attr("checked")){
            powody[1] = powod2.val();
        }else{
            powody[1] = '';
        }
        if(powod3.attr("checked")){
            powody[2] = powod3.val();
        }else{
            powody[2] = '';
        }
        if(powod4.attr("checked")){
            powody[3] = powod4.val();
        }else{
            powody[3] = '';
        }
        if(powod5.attr("checked")){
            powody[4] = powod5.val();
        }else{
            powody[4] = '';
        }
        if(powod6.val()!=""){
            powody[5] = powod6.val();
        }else{
            powody[5] = '';
        }
		
	
        $('#prompt_box2').fadeOut('slow');
        jQuery.post('/softdel,'+id+','+uid+'.html', {
            'powody[]': [powody[0],powody[1],powody[2],powody[3],powody[4],powody[5]]
        }, function(data){
            if(data=='1')
            {
                if(redirect==undefined) redirect = '/index.html';
                msgBox('Przedmiot został ukryty',1, redirect);
                if(toHide!=undefined) jQuery(toHide).hide();
            }
            else
            {
                msgBox('Przedmiot nie został ukryty',0);
            }
        });
    }else{
        alert("Musisz wybrać przynajmniej jeden powód");
    }
}

function doActAdm(link, question, back){
    if(confirm(question)){
        jQuery.get(link, function(data){
            if(data=='1'){
                msgBox('OK', 1, back);
            } else {
                msgBox('Wystąpił błąd!',0);
            }
        });
    }
    return false;
}

function sendMiniMail() {
    return true;
    advAJAX.assign(document.getElementById("miniMailform2"), {
        onSuccess : function(obj) {

            document.getElementById('miniMailForm').style.display = "none";

            if (obj.responseText == "1"){
                msgBox('Wiadomość została wysłana!', 1);
            }else{
                msgBox('Wiadomość NIE została wysłana!', 0);
            }
        }
    });
}

function send_email(uid){
    var form = '<input type="hidden" name="email_uid" id="email_uid" value="'+uid+'"/><p style="text-align: left;"><strong>Treść wiadomości:</strong><br/><textarea rows="10" cols="10" name="email_body" id="email_body" style=" padding: 5px; width: 350px; border: 1px solid black;"></textarea></p>';
    show_email_box("Wysyłanie wiadomości", form);
    return false;
}
function send_email_form(){
    $('#email_box2').fadeOut('slow');
    var id = $("#email_uid").val();
    var body = $("#email_body").val();
    jQuery.post('/ajax-sendEmail.html', {
        id: id,
        body: body
    }, function(data){
        if(data=='1')
        {
            $('#email_box2').fadeOut('slow');
            msgBox('Wiadomość została wysłana.',1);
        }
        else
        {
            $('#email_box2').fadeOut('slow');
            msgBox('Wystąpił błąd! Wiadomość NIE została wysłana.',0);
        }
    });
}

function usunKomentarz(id, pole, who){
    var adres = "/ajax/delCom.php?id="+id+"&who="+who;
    advAJAX.get({
        url: adres,
        onLoading:function(obj) {
            document.getElementById(pole).innerHTML='<div align="center">Trwa usuwanie...</div>';
        },
        onSuccess:function(obj) {
            document.getElementById(pole).innerHTML='';
            initLytebox();
        },
        onError:function(obj) {
            alert(obj.responseText);
        }
    });
}

function backSell(id, status){
    var adres = "/ajax/back_sell.php?back_id="+id+"&status="+status;
    jQuery.ajax({
        url: adres,
        success:function(obj) {
            jQuery('#bbacksell').html('Wysłano wiadomość');
            if(obj=='2') setTimeout(document.location="wiadomosci/moje-oferty.html", 2000);
        },
        error:function(obj) {
            alert("Wystąpił błąd");
        }
    });
    return false;
}

function sprawdzWiadomosc(){
    var radios = jQuery(':radio');
    if(radios.size()==3){
        if(!radios.is(':checked'))
        {
            alert('Wybierz Typ komentarza');
            return false;
        }
    }
    if(document.miniMailform2.wiadomosc.value==""){
        alert("Proszę uzupełnić treść.");
        return false;
    }
}

function openClose(id)
{
    $('#'+id).toggle();
}

function showMbTab(tab){
    $('#mb_tab_0').attr('class', 'tabs_mailbox_all');
    $('#mb_tab_1').attr('class', 'tabs_mailbox_shop');
    $('#mb_tab_2').attr('class', 'tabs_mailbox_plain');
    if(tab==0){
        $('#mb_tab_0').attr('class', 'tabs_mailbox_all-a');
        $('#mb_tab-1').fadeOut('fast');
        $('#mb_tab-2').fadeOut('fast');
        $('#mb_tab-0').fadeIn('fast');
    }else if(tab==1){
        $('#mb_tab_1').attr('class', 'tabs_mailbox_shop-a');
        $('#mb_tab-0').fadeOut('fast');
        $('#mb_tab-2').fadeOut('fast');
        $('#mb_tab-1').fadeIn('fast');
    }else if(tab==2){
        $('#mb_tab_2').attr('class', 'tabs_mailbox_plain-a');
        $('#mb_tab-1').fadeOut('fast');
        $('#mb_tab-0').fadeOut('fast');
        $('#mb_tab-2').fadeIn('fast');
    }
}


function showMailForm(offer)
{
    var frm = $('#miniMailform2');
    $('#forCId', frm).remove();
    if($('#miniMailForm').toggle().is(':visible'))
    {
        $('input[name=temat]', frm).val('');
        $('textarea', frm).val('');
    }
    if(!offer)
    {
        $('input[name=temat]', frm).removeAttr('readonly').val('');
    }
    else
    {
        var bck = $('#mMF_bck');
        $('input[name=temat]', frm).removeAttr('readonly').val($('span', bck).text());
        frm.append($('input', bck).clone());
    }
}

function reportAbuse(url, type, id, reason, result_id)
{
    $.ajax({
        type: "POST",
        url: url,
        data: "type="+type+"&id="+id+"&abuse_reason="+reason,
        success: function(msg){
            $(result_id).html('<p style="margin-left:5px; color: #B990A1; font-weight:bold">Zgłoszenie zostało wysłane</p>');
        }
    });
    return false;
}

function dodOpis(id){
    document.getElementById('ukryty_opis1').style.display = (document.getElementById('ukryty_opis1').style.display == "none") ? "block" : "none";
}
function dodOpis2(id){
    if(id==1){
        document.getElementById('ukryty_opis3').style.display = "block";
        document.getElementById('ukryty_opis2').style.display = "none";
    }else{
        document.getElementById('ukryty_opis2').style.display = "block";
        document.getElementById('ukryty_opis3').style.display = "none";
    }
//document.getElementById('ukryty_opis2').style.display = (document.getElementById('ukryty_opis2').style.display == "none") ? "block" : "none";
//document.getElementById('ukryty_opis3').style.display = (document.getElementById('ukryty_opis3').style.display == "none") ? "block" : "none";
}

function doAction(id,akcja,fid)
{
    $('#miniMailForm').hide();
    if(akcja=='cloth_fav'){
        var par = {
            'fid':fid,
            'type':'cloth'
        };
        $.get("/ajax-addToFav.html", par, function(result) {
            if(result=='1')
            {
                msgBox('Przedmiot został dodany do ulubionych',1);
            }
            else
            {
                msgBox('Masz już to w ulubionych',0);
            }
        }, 'text');

    }
    if(akcja=='user_fav'){
        var par = {
            'fid':fid,
            'type':'user'
        };
        $.get("/ajax-addToFav.html", par, function(result) {
            if(result=='1')
            {
                msgBox('Użytkowniczka została dodana do obserwowanych.',1);
            }
            else
            {
                msgBox('Już obserwujesz tę użytkowniczkę',0);
            }
        }, 'text');
    }
}

function sprawdzUstawienia(){

    if(document.ustawienia_form.apassword.value!="" && document.ustawienia_form.apassword.value!="" && document.ustawienia_form.apassword.value!=""){

        if(document.ustawienia_form.apassword.value==""){
            alert("Proszę uzupełnić pole oznaczone jako aktualne hasło.");
            return false;
        }
        if(document.ustawienia_form.apassword.value==document.ustawienia_form.npassword1.value){
            alert("Nowe i aktualne hasło nie mogą być takie same!");
            return false;
        }
        if(document.ustawienia_form.npassword1.value!=document.ustawienia_form.npassword2.value){
            alert("Nowe hasło z obu pól musi być takie samo!");
            return false;
        }

    }
    if(document.ustawienia_form.email.value==""){
        alert("Proszę uzupełnić pole oznaczone jako e-mail.");
        return false;
    }

    if(document.ustawienia_form.email.value!=document.ustawienia_form.old_email.value){
        return confirm('Zmieniłaś adres email i musisz dokonać jego aktywacji.\n\nJeśli jesteś pewna jego poprawności kliknij OK - zostaniesz wylogowana i na podany adres '+document.ustawienia_form.email.value+' otrzymasz e-mail z linkiem aktywacyjnym.\n\n W przeciwnym wypadku kliknij Anuluj i podaj poprawny email');

    }

    if(document.ustawienia_form.avatar.value!=""){

        var ext = document.ustawienia_form.avatar.value;
        ext = ext.substring(ext.length-3,ext.length);
        ext = ext.toLowerCase();
        if(ext != 'jpg') {
            alert('Avatar musi być plikiem JPG');
            return false;
        }else{
            return true;
        }
    }

    return true;
}
function sprawdzKontakt(){

    var dobryEmail=/^[^@]+@([a-z0-9\-]+\.)+[a-z]{2,4}$/i;

    if(document.kontakt_form.temat.value==""){
        alert("Proszę wybrac temat wiadomości.");
        return false;
    }
    if(document.kontakt_form.email.value==""){
        alert("Proszę wpisać swój adres email.");
        return false;
    }
    if(document.kontakt_form.wiadomosc.value==""){
        alert("Proszę wpisać treść wiadomości.");
        return false;
    }
    if (!dobryEmail.test(document.kontakt_form.email.value)){
        alert("Niepoprawny adres email!");
        return false;
    }

    return true;
}


function rozwinFiltr(){
    document.getElementById('filtr_lewa_rozw').style.display='none';
    document.getElementById('filtr_lewa_content').style.display='';
    document.getElementById('filtr_lewa_zwin').style.display='';
    createCookie('filter',1);
}
function zwinFiltr(){
    document.getElementById('filtr_lewa_zwin').style.display='none';
    document.getElementById('filtr_lewa_content').style.display='none';
    document.getElementById('filtr_lewa_rozw').style.display='';
    createCookie('filter',0);
}



function sprawdzKomentarz(){

    if(document.komentarz.clothID.value==""){
        alert("Wystąpił nieokreślony błąd.");
        return false;
    }
    if(document.komentarz.komentarz.value==""){
        alert("Proszę wpisać komentarz.");
        return false;
    }
    return true;

}

/*wysylanie zaproszen mailem*/
function dodaj_nowe_pole_mail()
{
    var frm = $('#zaproszeniaMail');
    var wyslanie = $('input[name=wyslij_zaproszenie]');
    $(wyslanie, frm).before("<input name=\"mail[]\" onBlur=\"checkemail(this)\" type=\"text\" class=\"zaproszenia_mail_pole\" />");
    $(".zaproszenia_mail_pole:last").one("click", dodaj_nowe_pole_mail)
/*$("#btn_dodaj_pole").remove().insertBefore(wyslanie); */
}

function accountIBAN(){
    var f=jQuery('input[name=rachunek]');
    account = f.val();
    account = account.replace(/[^0-9]/,'');
    if (length(account) != 26) return [[f, 'Numer konta musi się składać z 26 cyfr']];
    vno = account.substring(2) + '2521' + account.substring(0, 2);
    v = 0;
    for(i = 0; i < 30; ++i) {
        v = (v + (vno[i] + 0) * w[i]) % 97;
    }
    return v == 1?true:[[f, 'Niepoprawny numer konta']];
}
function szafa_analytics(iurl){
    jQuery.get('/ajax-functions.html', {
        action:'analytics',
        url:iurl
    });
}




function filterForms(){
    var cat = $("#cat").val();
    var dla = $("#filterdla").val();
    var color = $("#filtercolor").val();
    var manufacturer = $("#filter-manufacturer").val();
    var province = $("#filter-province").val();
    var size = $("#filter-size").val();
    if(size=='undefined' || size==undefined) size = '';
    var type = $("#filter-type").val();
    var price_from = $("#filter_price_from").val();
    var price_to = $("#filter_price_to").val();
		
    var path = "";
    if(cat!="" && cat!='undefined' && cat!=undefined && cat!='*') path = path+cat+"/";
    if(color!="" && color!="*") path = path+"kolor-"+color+"/";
    if(size!="") path = path+"rozmiar-"+size+"/";
    if(manufacturer!="" && manufacturer!="undefined" && manufacturer!=undefined) path = path+"producent-"+manufacturer+"/";
    if(province!="") path = path+"wojewodztwo-"+province+"/";
    if(price_from!="" && price_to!="" && (price_from>0 || price_to<500)) path = path+"cena-"+price_from+"-"+price_to+"/";
    if(type!="" && type!=0) path = path+"typ-"+type+"/";
    if(dla!="" && dla!=0 && dla!='undefined' && dla!=undefined) path = path+"dla-"+dla+"/";
    pageTracker._trackPageview('/filtrowanie');
    window.location="/"+path;
    window.location.href="/"+path;
    window.event.returnValue = false;
}

function filterSearch(){
    var cat = $("#search_cat").val();
    var subcat = $("#search_subcat").val();
    var color = $("#search_color").val();
    var manufacturer = $("#search_manufacturer").val();
    var province = $("#search_province").val();
    var size = $("#search_size").val();
    if(size=='undefined' || size==undefined) size = '';
    var type = $("#search_type").val();
    var price_from = $("#search_price_from").val();
    var price_to = $("#search_price_to").val();
    var added = $("#search_added").val();
    var query = $("#search_query2").val();
    var page = $("#search_page").val();
    var orderby = $("#orderby").val();
    var miasto = $("#search_city").val();
		
    if(page!=undefined && page!="" && page!='undefined')
        var path = "szukaj/"+query+"/"+page+"/";
    else
        var path = "szukaj/"+query+"/";
		
    if(cat!="" && cat!='undefined' && cat!=undefined && cat!='*') path = path+"kategoria-"+cat+"/";
    if(subcat!="" && subcat!='undefined' && subcat!=undefined && subcat!='*') path = path+"podkategoria-"+subcat+"/";
    if(color!="" && color!="*") path = path+"kolor-"+color+"/";
    if(size!="") path = path+"rozmiar-"+size+"/";
    if(manufacturer!="" && manufacturer!="undefined" && manufacturer!=undefined) path = path+"producent-"+manufacturer+"/";
    if(province!="") path = path+"wojewodztwo-"+province+"/";
    if(added!="") path = path+"dodano-"+added+"/";
    if(price_from!="" && price_to!="" && (price_from>0 || price_to<500)) path = path+"cena-"+price_from+"-"+price_to+"/";
    if(type!="" && type!=0) path = path+"typ-"+type+"/";
    if(orderby!="" && orderby!="trafnosc" && orderby!="undefined" && orderby!=undefined) path = path+"sortuj-po-"+orderby+"/";
    if(miasto!="" && miasto!="undefined" && miasto!=undefined) path = path+"?miasto="+miasto;
    window.location="/"+path;
    window.location.href="/"+path;
    window.event.returnValue = false;
    return false;
}
	  
function loadSubCategories(html_name){
    if(html_name==""){
        $("#search_subcat").val("");
    //filterSearch();
    }else{
        // przeladowanie podkategorii
        $('.subcat_box').html("<p style='text-align: center'>Trwa ładowanie...</p>");
        $.get('/ajax-loadSubCategories.html', {
            html_name: html_name
        }, function(data) {
            $('.subcat_box').html("");
            $('.subcat_box').html(data);
        })
        // przeladowanie rozmiarów
        $("#search_size").removeOption(/./).ajaxAddOption("/ajax-dictionary.html", {
            name: "sizesNCAT",
            cname: html_name,
            _html_name: 1
        }, false);
        $("#search_size").css("color", "black");
    }
}
	  
function loadSizes(html_name){
    if(html_name!=""){
        // przeladowanie rozmiarów
        $("#search_size").removeOption(/./).ajaxAddOption("/ajax-dictionary.html", {
            name: "sizesN",
            cname: html_name,
            _html_name: 1
        }, false);
        $("#search_size").css("color", "black");
    }
}

function sug_vote(type, sug_id){
    if(confirm("Czy na pewno chcesz zagłosować na tę sugestię?")){
        $.post("/ajax-sugVote.html", {
            sug_type:type,
            sug_id:sug_id
        },
        function(returned_data)
        {
            alert(returned_data);
            location.href=location.href;
            window.location.href=window.location.href;
        });
        return true;
    }else{
        return false;
    }
}  function onlyPlain(event,f)
{
	if (event.srcElement) {kc = event.keyCode;} else {kc = event.which;}
	if ((kc < 48 || kc > 57) && (kc < 65 || kc > 90) && (kc < 97 || kc > 122) && kc != 45 && kc != 46 && kc != 95 && kc != 8 && kc != 0) return false;
	return true;
}function disallowedCharacters(event,f)
{
	if (event.srcElement) {kc = event.keyCode;} else {kc = event.which;}
	if ((kc < 34 || kc > 39) && (kc < 91 || kc > 96) && kc != 64 && (kc < 60 || kc > 62) && (kc < 123 || kc > 126) && kc != 42 && kc != 45 && kc == 0) return true;
	return false;
}function onlyPlainLogin(event,f)
{
	if (event.srcElement) {kc = event.keyCode;} else {kc = event.which;}
	if ((kc < 48 || kc > 57) && (kc < 65 || kc > 90) && (kc < 97 || kc > 122) && kc != 45 && kc != 95 && kc != 8 && kc != 0 && kc != 127) return false;
	return true;
}function openClose(id)
{
    $('#'+id).toggle();
}
function pokazFormularzLogowania(){	document.getElementById('btn_rejestracja').style.display='none';
	document.getElementById('btn_zaloguj_sie').style.display='none';
	document.getElementById('formularzLogowania').style.display='inline';}
function ukryjFormularzLogowania(){	document.getElementById('btn_rejestracja').style.display='inline';
	document.getElementById('btn_zaloguj_sie').style.display='inline';
	document.getElementById('formularzLogowania').style.display='none';
}function sprawdzLogowanie(){	if(document.logowanie.login.value==""){
		alert("Proszę uzupełnić pole oznaczone jako login.");
		return false;
	}
	if(document.logowanie.password.value==""){
		alert("Proszę uzupełnić pole oznaczone jako hasło.");
		return false;
	}
	return true;}function sprawdzLogowanie2(){	if(document.logowanie2.login.value==""){
		alert("Proszę uzupełnić pole oznaczone jako login.");
		return false;
	}
	if(document.logowanie2.password.value==""){
		alert("Proszę uzupełnić pole oznaczone jako hasło.");
		return false;
	}
	return true;}function sprawdzRejestracje(){var dobryEmail=/^[^@]+@([a-z0-9\-]+\.)+[a-z]{2,4}$/i;
var dobryLogin=/^([AZa-z0-9\-\_]+)$/i;	if(document.rejestracja.login.value==""){
		alert("Proszę uzupełnić pole oznaczone jako login.");
		return false;
	}
	if(document.rejestracja.login.value.length<4){
		alert("Twój login musi być dłuższy niż 4 znaki.");
		return false;
	}
	if (!dobryLogin.test(document.rejestracja.login.value)){
	alert("W polu login wystąpiły niedozwolone znaki!");
	return false;
	}
	if(document.rejestracja.email.value==""){
		alert("Proszę uzupełnić pole oznaczone jako email.");
		return false;
	}
	if (!dobryEmail.test(document.rejestracja.email.value)){
	alert("Niepoprawny adres email!");
	return false;
	}
	if(document.rejestracja.password.value==""){
		alert("Proszę uzupełnić pole oznaczone jako hasło.");
		return false;
	}
	if(document.rejestracja.password.value.length<4){
		alert("Hasło musi być dłuższe niż 4 znaki.");
		return false;
	}
	if(document.rejestracja.login.value==document.rejestracja.password.value){
		alert("Login i hasło nie mogą być takie same");
		return false;
	}
	if(document.rejestracja.regulamin.checked==false){
		alert("Jeśli chcesz się zarejestrować, musisz zaakceptować warunki regulaminu Szafa.pl.");
		return false;
	}
	return true;}/*cookies*/
function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}function eraseCookie(name) {
	createCookie(name,"",-1);
}function checkemail(inp)
{
	var str = inp.value;
	var filter=/^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i
	if (filter.test(str))
	{
	testresults=true;
	inp.style.backgroundColor = 'white';
	$('#rej_error').css("display","none");
	}
	else{
	inp.style.backgroundColor = 'red';
	$('#rej_error').css("display","block");
	testresults=false;
	}
	return (testresults)
}function validateEx(type, el, mode){
	if(mode == undefined) mode = 1;
	var f = jQuery(el);
	if(f.val()!=''){
		jQuery.get('/ajax/dictionary.php', {'type':type, 'value':f.val()}, function(data, status){
			f.next('div').remove();
			if(mode){
			    if(data=='1') {
				    var msg = (type==3 || type==5)?'Login jest już zajęty':'Adres e-mail został już użyty';
				    f.after('<div style="color: red; text-align: right; padding-right: 40px">' + msg + '</div>');
				    f.one('keypress', function(){f.next('div').remove();});
			    }
			} else {
			    if(data=='0') {
				    var msg = (type==3 || type==5)?'Login nie istnieje':'Adres e-mail nie istnieje';
				    f.after('<div style="color: red; text-align: right; padding-right: 40px">' + msg + '</div>');
				    f.one('keypress', function(){f.next('div').remove();});
			    }
			}
		}, 'text');
	}
}function SDMenu(id) {
	this.menu = $('#'+id);
	if(this.menu == null) return false;
	this.submenus = this.menu.children('div');
	this.remember = true;
	this.speed = 600;
	this.markCurrent = false;
	this.oneSmOnly = true;
	return this;
}
SDMenu.prototype.init = function() {
	var th = this;
	this.submenus.each(function(){
		sb = $(this);
		sb.children('div').bind('click', sb, function(e){
			if(e.data.hasClass('collapsed'))
			{
				th.expandMenu(e.data);
			}
			else
			{
				th.collapseMenu(e.data);
			}
		});
	});
};
SDMenu.prototype.toggleMenu = function(submenu) {
	if (submenu.hasClass('collapsed'))
	{
		this.expandMenu(submenu);
	}
	else
	{
		this.collapseMenu(submenu);
	}
};
SDMenu.prototype.expandMenu = function(submenu) {
	var fullHeight = 0;
	submenu.children('p,div').each(function(){
		fullHeight += $(this).outerHeight();
	});
	submenu.removeClass('collapsed')
	submenu.animate({height: fullHeight + 'px'}, this.speed);
	this.collapseOthers(submenu);
};
SDMenu.prototype.collapseMenu = function(submenu) {
	var minHeight = submenu.children('div').outerHeight();
	submenu.addClass('collapsed');
	submenu.animate({height: minHeight + 'px'}, this.speed);
};
SDMenu.prototype.collapseOthers = function(submenu) {
	if (this.oneSmOnly) {
		th = this;
		submenu.siblings('div').not('collapsed').each(function(){
			th.collapseMenu($(this));
		});
	}
};
SDMenu.prototype.expandAll = function() {
	var oldOneSmOnly = this.oneSmOnly;
	this.oneSmOnly = false;
	var th = this;
	this.submenus.filter('.collapsed').each(function(){	th.expandMenu($(this)); });
	this.oneSmOnly = oldOneSmOnly;
};
SDMenu.prototype.collapseAll = function() {
	this.submenus.not('.collapsed').each(function(){th.collapseMenu($(this)); });
};var DDSPEED = 10;
var DDTIMER = 15;

// main function to handle the mouse events //
function ddMenu(id,d){
  var h = document.getElementById(id + '-ddheader');
  var c = document.getElementById(id + '-ddcontent');
  clearInterval(c.timer);
  if(d == 1){
    clearTimeout(h.timer);
    if(c.maxh && c.maxh <= c.offsetHeight){return}
    else if(!c.maxh){
      c.style.display = 'block';
      c.style.height = 'auto';
      c.maxh = c.offsetHeight;
      c.style.height = '0px';
    }
    c.timer = setInterval(function(){ddSlide(c,1)},DDTIMER);
  }else{
    h.timer = setTimeout(function(){ddCollapse(c)},50);
  }
}

// collapse the menu //
function ddCollapse(c){
  c.timer = setInterval(function(){ddSlide(c,-1)},DDTIMER);
}

// cancel the collapse if a user rolls over the dropdown //
function cancelHide(id){
  var h = document.getElementById(id + '-ddheader');
  var c = document.getElementById(id + '-ddcontent');
  clearTimeout(h.timer);
  clearInterval(c.timer);
  if(c.offsetHeight < c.maxh){
    c.timer = setInterval(function(){ddSlide(c,1)},DDTIMER);
  }
}

// incrementally expand/contract the dropdown and change the opacity //
function ddSlide(c,d){
  var currh = c.offsetHeight;
  var dist;
  if(d == 1){
    dist = (Math.round((c.maxh - currh) / DDSPEED));
  }else{
    dist = (Math.round(currh / DDSPEED));
  }
  if(dist <= 1 && d == 1){
    dist = 1;
  }
  c.style.height = currh + (dist * d) + 'px';
  c.style.opacity = currh / c.maxh;
  c.style.filter = 'alpha(opacity=' + (currh * 100 / c.maxh) + ')';
  if((currh < 2 && d != 1) || (currh > (c.maxh - 2) && d == 1)){
    clearInterval(c.timer);
  }
}

