/*
 * jQuery Form Plugin
 * version: 2.21 (08-FEB-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(e) {
      e.preventDefault(); // <-- important
      $(this).ajaxSubmit({
        target: '#output'
      });
    });
  });

  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;
  }
  
  var method, action, url, $form = this;

  if (typeof options == 'function') {
    options = { success: options };
  }

  method = this.attr('method');
  action = this.attr('action');
  url = (typeof action === 'string') ? $.trim(action) : '';
  url = url || window.location.href || '';
  if (url) {
    // clean url (don't include hash vaue)
    url = (url.match(/^([^#]+)/)||[])[1];
  }

  options = $.extend(true, {
    url:  url,
    success: $.ajaxSettings.success,
    type: method || 'GET',
    iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
  }, 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 n,v,a = this.formToArray(options.semantic);
  if (options.data) {
    options.extraData = options.data;
    for (n in options.data) {
      if( $.isArray(options.data[n]) ) {
        for (var k in options.data[n]) {
          a.push( { name: n, value: options.data[n][k] } );
        }
      }
      else {
        v = options.data[n];
        v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
        a.push( { name: n, value: v } );
      }
    }
  }

  // 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 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) {
      var fn = options.replaceTarget ? 'replaceWith' : 'html';
      $(options.target)[fn](data).each(oldSuccess, arguments);
    });
  }
  else if (options.success) {
    callbacks.push(options.success);
  }

  options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
    var context = options.context || options;   // jQuery 1.4+ supports scope context 
    for (var i=0, max=callbacks.length; i < max; i++) {
      callbacks[i].apply(context, [data, status, xhr || $form, $form]);
    }
  };

  // are there files to upload?
  var fileInputs = $('input:file', this).length > 0;
  var mp = 'multipart/form-data';
  var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);

  // options.iframe allows user to force iframe mode
  // 06-NOV-09: now defaulting to iframe mode if file input is detected
   if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
     // 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, function() { fileUpload(a); });
    }
     else {
       fileUpload(a);
    }
   }
   else {
    // IE7 massage (see issue 57)
    if ($.browser.msie && method == 'get') { 
      var ieMeth = $form[0].getAttribute('method');
      if (typeof ieMeth === 'string')
        options.type = ieMeth;
    }
    $.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(a) {
    var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
        var useProp = !!$.fn.prop;

        if (a) {
          // ensure that every serialized input is still enabled
            for (i=0; i < a.length; i++) {
                el = $(form[a[i].name]);
                el[ useProp ? 'prop' : 'attr' ]('disabled', false);
            }
        }

    if ($(':input[name=submit],:input[id=submit]', form).length) {
      // if there is an input with a name or id of 'submit' then we won't be
      // able to invoke the submit fn on the form (at least not x-browser)
      alert('Error: Form elements must not have name or id of "submit".');
      return;
    }
    
    s = $.extend(true, {}, $.ajaxSettings, options);
    s.context = s.context || s;
    id = 'jqFormIO' + (new Date().getTime());
    if (s.iframeTarget) {
      $io = $(s.iframeTarget);
      n = $io.attr('name');
      if (n == null)
        $io.attr('name', id);
      else
        id = n;
    }
    else {
      $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
      $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
    }
    io = $io[0];


    xhr = { // mock object
      aborted: 0,
      responseText: null,
      responseXML: null,
      status: 0,
      statusText: 'n/a',
      getAllResponseHeaders: function() {},
      getResponseHeader: function() {},
      setRequestHeader: function() {},
      abort: function(status) {
        var e = (status === 'timeout' ? 'timeout' : 'aborted');
        log('aborting upload... ' + e);
        this.aborted = 1;
        $io.attr('src', s.iframeSrc); // abort op in progress
        xhr.error = e;
        s.error && s.error.call(s.context, xhr, e, status);
        g && $.event.trigger("ajaxError", [xhr, s, e]);
        s.complete && s.complete.call(s.context, xhr, e);
      }
    };

    g = s.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, s]);
    }

    if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
      if (s.global) {
        $.active--;
      }
      return;
    }
    if (xhr.aborted) {
      return;
    }

    // add submitting element to data if we know it
    sub = form.clk;
    if (sub) {
      n = sub.name;
      if (n && !sub.disabled) {
        s.extraData = s.extraData || {};
        s.extraData[n] = sub.value;
        if (sub.type == "image") {
          s.extraData[n+'.x'] = form.clk_x;
          s.extraData[n+'.y'] = form.clk_y;
        }
      }
    }
    
    var CLIENT_TIMEOUT_ABORT = 1;
    var SERVER_ABORT = 2;

    function getDoc(frame) {
      var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
      return doc;
    }
    
    // take a breath so that pending repaints get some cpu time before the upload starts
    function doSubmit() {
      // 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 (!method) {
        form.setAttribute('method', 'POST');
      }
      if (a != s.url) {
        form.setAttribute('action', s.url);
      }

      // ie borks in some cases when setting encoding
      if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
        $form.attr({
          encoding: 'multipart/form-data',
          enctype:  'multipart/form-data'
        });
      }

      // support timout
      if (s.timeout) {
        timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
      }
      
      // look for server aborts
      function checkState() {
        try {
          var state = getDoc(io).readyState;
          log('state = ' + state);
          if (state.toLowerCase() == 'uninitialized')
            setTimeout(checkState,50);
        }
        catch(e) {
          log('Server abort: ' , e, ' (', e.name, ')');
          cb(SERVER_ABORT);
          timeoutHandle && clearTimeout(timeoutHandle);
          timeoutHandle = undefined;
        }
      }

      // add "extra" data to form if provided in options
      var extraInputs = [];
      try {
        if (s.extraData) {
          for (var n in s.extraData) {
            extraInputs.push(
              $('<input type="hidden" name="'+n+'" />').attr('value',s.extraData[n])
                .appendTo(form)[0]);
          }
        }

        if (!s.iframeTarget) {
          // add iframe to doc and submit the form
          $io.appendTo('body');
                  io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
        }
        setTimeout(checkState,15);
        form.submit();
      }
      finally {
        // reset attrs and remove "extra" input elements
        form.setAttribute('action',a);
        if(t) {
          form.setAttribute('target', t);
        } else {
          $form.removeAttr('target');
        }
        $(extraInputs).remove();
      }
    }

    if (s.forceSync) {
      doSubmit();
    }
    else {
      setTimeout(doSubmit, 10); // this lets dom updates render
    }

    var data, doc, domCheckCount = 50, callbackProcessed;

    function cb(e) {
      if (xhr.aborted || callbackProcessed) {
        return;
      }
      try {
        doc = getDoc(io);
      }
      catch(ex) {
        log('cannot access response document: ', ex);
        e = SERVER_ABORT;
      }
      if (e === CLIENT_TIMEOUT_ABORT && xhr) {
        xhr.abort('timeout');
        return;
      }
      else if (e == SERVER_ABORT && xhr) {
        xhr.abort('server abort');
        return;
      }

      if (!doc || doc.location.href == s.iframeSrc) {
        // response not received yet
        if (!timedOut)
          return;
      }
            io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);

      var status = 'success', errMsg;
      try {
        if (timedOut) {
          throw 'timeout';
        }

        var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
        log('isXml='+isXml);
        if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
          if (--domCheckCount) {
            // in some browsers (Opera) the iframe DOM is not always traversable when
            // the onload callback fires, so we loop a bit to accommodate
            log('requeing onLoad callback, DOM not available');
            setTimeout(cb, 250);
            return;
          }
          // let this fall through because server response could be an empty document
          //log('Could not access iframe DOM after mutiple tries.');
          //throw 'DOMException: not available';
        }

        //log('response detected');
                var docRoot = doc.body ? doc.body : doc.documentElement;
                xhr.responseText = docRoot ? docRoot.innerHTML : null;
        xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
        if (isXml)
          s.dataType = 'xml';
        xhr.getResponseHeader = function(header){
          var headers = {'content-type': s.dataType};
          return headers[header];
        };
                // support for XHR 'status' & 'statusText' emulation :
                if (docRoot) {
                    xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
                    xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
                }

        var dt = s.dataType || '';
        var scr = /(json|script|text)/.test(dt.toLowerCase());
        if (scr || s.textarea) {
          // see if user embedded response in textarea
          var ta = doc.getElementsByTagName('textarea')[0];
          if (ta) {
            xhr.responseText = ta.value;
                        // support for XHR 'status' & 'statusText' emulation :
                        xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
                        xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
          }
          else if (scr) {
            // account for browsers injecting pre around json response
            var pre = doc.getElementsByTagName('pre')[0];
            var b = doc.getElementsByTagName('body')[0];
            if (pre) {
              xhr.responseText = pre.textContent ? pre.textContent : pre.innerHTML;
            }
            else if (b) {
              xhr.responseText = b.innerHTML;
            }
          }
        }
        else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
          xhr.responseXML = toXml(xhr.responseText);
        }

                try {
                    data = httpData(xhr, s.dataType, s);
                }
                catch (e) {
                    status = 'parsererror';
                    xhr.error = errMsg = (e || status);
                }
      }
      catch (e) {
        log('error caught: ',e);
        status = 'error';
                xhr.error = errMsg = (e || status);
      }

      if (xhr.aborted) {
        log('upload aborted');
        status = null;
      }

            if (xhr.status) { // we've set xhr.status
                status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
            }

      // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
      if (status === 'success') {
        s.success && s.success.call(s.context, data, 'success', xhr);
        g && $.event.trigger("ajaxSuccess", [xhr, s]);
      }
            else if (status) {
        if (errMsg == undefined)
          errMsg = xhr.statusText;
        s.error && s.error.call(s.context, xhr, status, errMsg);
        g && $.event.trigger("ajaxError", [xhr, s, errMsg]);
            }

      g && $.event.trigger("ajaxComplete", [xhr, s]);

      if (g && ! --$.active) {
        $.event.trigger("ajaxStop");
      }

      s.complete && s.complete.call(s.context, xhr, status);

      callbackProcessed = true;
      if (s.timeout)
        clearTimeout(timeoutHandle);

      // clean up
      setTimeout(function() {
        if (!s.iframeTarget)
          $io.remove();
        xhr.responseXML = null;
      }, 100);
    }

    var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
      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.nodeName != 'parsererror') ? doc : null;
    };
    var parseJSON = $.parseJSON || function(s) {
      return window['eval']('(' + s + ')');
    };

    var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4

      var ct = xhr.getResponseHeader('content-type') || '',
        xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
        data = xml ? xhr.responseXML : xhr.responseText;

      if (xml && data.documentElement.nodeName === 'parsererror') {
        $.error && $.error('parsererror');
      }
      if (s && s.dataFilter) {
        data = s.dataFilter(data, type);
      }
      if (typeof data === 'string') {
        if (type === 'json' || !type && ct.indexOf('json') >= 0) {
          data = parseJSON(data);
        } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
          $.globalEval(data);
        }
      }
      return data;
    };
  }
};

/**
 * 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) {
  // in jQuery 1.3+ we can fix mistakes with the ready state
  if (this.length === 0) {
    var o = { s: this.selector, c: this.context };
    if (!$.isReady && o.s) {
      log('DOM not ready, queuing ajaxForm');
      $(function() {
        $(o.s,o.c).ajaxForm(options);
      });
      return this;
    }
    // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
    log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
    return this;
  }

  return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
    if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
      e.preventDefault();
      $(this).ajaxSubmit(options);
    }
  }).bind('click.form-plugin', function(e) {
    var target = e.target;
    var $el = $(target);
    if (!($el.is(":submit,input:image"))) {
      // is this a child element of the submit el?  (ex: a span within a button)
      var t = $el.closest(':submit');
      if (t.length == 0) {
        return;
      }
      target = t[0];
    }
    var form = this;
    form.clk = target;
    if (target.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 = $el.offset();
        form.clk_x = e.pageX - offset.left;
        form.clk_y = e.pageY - offset.top;
      } else {
        form.clk_x = e.pageX - target.offsetLeft;
        form.clk_y = e.pageY - target.offsetTop;
      }
    }
    // clear form vars
    setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
  });
};

// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function() {
  return this.unbind('submit.form-plugin 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;
  }

  var i,j,n,v,el,max,jmax;
  for(i=0, max=els.length; i < max; i++) {
    el = els[i];
    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, value: $(el).val()});
        a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
      }
      continue;
    }

    v = $.fieldValue(el, true);
    if (v && v.constructor == Array) {
      for(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 it here
    var $input = $(form.clk), input = $input[0];
    n = input.name;
    if (n && !input.disabled && input.type == 'image') {
      a.push({name: n, value: $input.val()});
      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 (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).val();
};

/**
 * 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() {
  var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
  return this.each(function() {
    var t = this.type, tag = this.tagName.toLowerCase();
    if (re.test(t) || 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
function log() {
  var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
  if (window.console && window.console.log) {
    window.console.log(msg);
  }
  else if (window.opera && window.opera.postError) {
    window.opera.postError(msg);
  }
};

$.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": "relative",
          "float": "left",
          "overflow": "hidden"
        }).addClass('fileStyle');

				var _once = false;
        $(self)
					.wrap(wrapper)
					.css({
            "position": "absolute",
            "left": -124,
            "height": settings.imageheight + "px",
            "width": settings.width + "px",
            "display": "inline",
            "opacity": 0
          }).click(function(eve) {
						//eve.stopPropagation();
					});


				$(self).parent('div.fileStyle')
					.click(function() {
						//$(self).trigger('click');
					});

        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");
        }
    });
};

})(jQuery);

/** {doc}
 * Software License Agreement (BSD License)
 * 
 * Copyright (c) 2008, Dave Hauenstein
 * All rights reserved.
 * 
 * Redistribution and use of this software in source and binary forms, with or
 * without modification, are permitted provided that the following conditions
 * are met:
 * 
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * 
 * - 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.
 * 
 * - Neither the name of Dave Hauenstein nor the names of its contributors may be
 *   used to endorse or promote products derived from this software without
 *   specific prior written permission of Dave Hauenstein
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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.
 */

/*
* @param String   options[url]                  url that post request will hit
* @param String   options[params]               paramters sent via the post request to the server; string; ex: name=dave&last_name=hauenstein
* @param String   options[field_type]           can be: text, textarea, select; default: text
* @param String   options[select_options]       this is a string seperated by commas for the dropdown options, if field_type is dropdown
* @param String   options[textarea_cols]        number of columns textarea will have, if field_type is textarea; default: 25
* @param String   options[textarea_rows]        number of rows textarea will have, if field_type is textarea; default: 10
* @param String   options[bg_over]              background color of editable elements on HOVER
* @param String   options[bg_out]               background color of editable elements on RESTORE from hover
* @param String   options[saving_text]          text to be used when server is saving information; default: 'Saving...'
* @param String   options[saving_image]         specify an image location instead of text while server is saving; default: uses saving text
* @param String   options[default_text]         text to show up if the element that has this functionality is empty
* @param String   options[select_text]          default text to show up in select box
* @param String   options[value_required]       if set to true, the element will not be saved unless a value is entered
* @param String   options[element_id]           name of parameter holding element_id; default: element_id
* @param String   options[update_value]         name of parameter holding update_value; default: update_value
* @param String   options[original_html]        name of parameter holding original_html; default: original_html
* @param String   options[save_button]          image button tag to use as "Save" button
* @param String   options[cancel_button]        image button tag to use as "Cancel" button
* @param String   options[show_buttons]         will show the buttons: cancel or save; will automatically cancel out the onBlur functionality
* @param String   options[on_blur]              what to do on blur: "save" or null; default: "save"; will be overridden if $param show_buttons is true
* @param Function options[callback]             call function instead of submitting to url
* @param Function options[success]              this function gets called if server responds with a success
* @param Function options[error]                this function gets called if server responds with an error
*/
jQuery.fn.editInPlace = function(options) {

    /* DEFINE THE DEFAULT SETTINGS, SWITCH THEM WITH THE OPTIONS USER PROVIDES */
  var settings = {

           url : "",
        params : "",
    field_type : "text",
select_options : "",
 textarea_cols : "25",
 textarea_rows : "10",
       bg_over : "#ffc",
        bg_out : "transparent",
   saving_text : "Saving...",
  saving_image : "",
  default_text : "(Click here to add text)",
   select_text : "Choose new value",
value_required : null,
    element_id : "element_id",
  update_value : "update_value",
 original_html : "original_html",
   save_button : '<input type="submit" class="inplace_save" value="Save"/>',
 cancel_button : '<input type="submit" class="inplace_cancel" value="Cancel"/>',
  show_buttons : false,
       on_blur : "save",
      callback : null,
       success : null,
         error : function(request){
                   alert("Failed to save value: " + request.responseText || 'Unspecified Error');
                 }
  };

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

    /* preload the loading icon if it exists */
    if(settings.saving_image != ""){
        var loading_image = new Image();
        loading_image.src = settings.saving_image;
    }

    /* THIS FUNCTION WILL TRIM WHITESPACE FROM BEFORE/AFTER A STRING */
    String.prototype.trim = function() {
        return this.replace(/^\s+/, '')
                             .replace(/\s+$/, '');
    };

    /* THIS FUNCTION WILL ESCAPE ANY HTML ENTITIES SO "Quoted Values" work */
    String.prototype.escape_html = function() {
        return this.replace(/&/g, "&amp;")
                             .replace(/</g, "&lt;")
                             .replace(/>/g, "&gt;")
                             .replace(/"/g, "&quot;");
  };

    /* CREATE THE INPLACE EDITOR */
    return this.each(function(){

        if(jQuery(this).html() == "") jQuery(this).html(settings.default_text);

        var editing = false;

        //save the original element - for change of scope
        var original_element = jQuery(this);

        var click_count = 0;

        jQuery(this)

        .mouseover(function(){
            jQuery(this).css("background", settings.bg_over);
        })

        .mouseout(function(){
            jQuery(this).css("background", settings.bg_out);
        })

        .click(function(){
            click_count++;

            if(!editing)
            {
                editing = true;

                //save original text - for cancellation functionality
                var original_html = jQuery(this).html();
                var buttons_code  = (settings.show_buttons) ? settings.save_button + ' ' + settings.cancel_button : '';

                //if html is our default text, clear it out to prevent saving accidentally
                if (original_html == settings.default_text) jQuery(this).html('');

                if (settings.field_type == "textarea")
                {
                    var use_field_type = '<textarea name="inplace_value" class="inplace_field" rows="' + settings.textarea_rows + '" cols="' + settings.textarea_cols + '">' + jQuery(this).text().trim().escape_html() + '</textarea>';
                }
                else if(settings.field_type == "text")
                {
                    var use_field_type = '<input type="text" name="inplace_value" class="inplace_field" value="' +
                                            jQuery(this).text().trim().escape_html() + '" />';
                }
                else if(settings.field_type == "select")
                {
                    var optionsArray = settings.select_options.split(',');
                    var use_field_type = '<select name="inplace_value" class="inplace_field"><option value="">' + settings.select_text + '</option>';
                        for(var i=0; i<optionsArray.length; i++){
                            var optionsValuesArray = optionsArray[i].split(':');
                            var use_value = optionsValuesArray[1] || optionsValuesArray[0];
                            var selected = use_value == original_html ? 'selected="selected" ' : '';
                            use_field_type += '<option ' + selected + 'value="' + use_value.trim().escape_html() + '">' + optionsValuesArray[0].trim().escape_html() + '</option>';
                        }
                        use_field_type += '</select>';
                }

                /* insert the new in place form after the element they click, then empty out the original element */
                jQuery(this).html('<form class="inplace_form" style="display: inline; margin: 0; padding: 0;">' + use_field_type + ' ' + buttons_code + '</form>');

            }/* END- if(!editing) -END */

            if(click_count == 1)
            {
                function cancelAction()
                {
                    editing = false;
                    click_count = 0;

                    /* put the original background color in */
                    original_element.css("background", settings.bg_out);

                    /* put back the original text */
                    original_element.html(original_html);

                    return false;
                }

                function saveAction()
                {
                    /* put the original background color in */
                    original_element.css("background", settings.bg_out);

                    var this_elem = jQuery(this);

                    var new_html = (this_elem.is('form')) ? this_elem.children(0).val() : this_elem.parent().children(0).val();

                    /* set saving message */
                    if(settings.saving_image != ""){
                        var saving_message = '<img src="' + settings.saving_image + '" alt="Saving..." />';
                    } else {
                        var saving_message = settings.saving_text;
                    }

                    /* place the saving text/image in the original element */
                    original_element.html(saving_message);

                    if(settings.params != ""){
                        settings.params = "&" + settings.params;
                    }

                    if(settings.callback) {
                        html = settings.callback(original_element.attr("id"), new_html, original_html, settings.params);
                        editing = false;
                        click_count = 0;
                        if (html) {
                            /* put the newly updated info into the original element */
                            original_element.html(html || new_html);
                        } else {
                            /* failure; put original back */
                            alert("Failed to save value: " + new_html);
                            original_element.html(original_html);
                        }
                    } else if (settings.value_required && (new_html == "" || new_html == undefined)) {
                        editing = false;
                        click_count = 0;
                        original_element.html(original_html);
                        alert("Error: You must enter a value to save this field");
                    } else {
                        jQuery.ajax({
                            url: settings.url,
                            type: "POST",
                            data: settings.update_value + '=' + new_html + '&' + settings.element_id + '=' + original_element.attr("id") + settings.params + '&' + settings.original_html + '=' + original_html,
                            dataType: "html",
                            complete: function(request){
                                editing = false;
                                click_count = 0;
                            },
                            success: function(html){
                                /* if the text returned by the server is empty, */
                                /* put a marker as text in the original element */
                                var new_text = html || settings.default_text;

                                /* put the newly updated info into the original element */
                                original_element.html(new_text);
                                if (settings.success) settings.success(html, original_element);
                            },
                            error: function(request) {
                                original_element.html(original_html);
                                if (settings.error) settings.error(request, original_element);
                            }
                        });
                    }

                    return false;
                }

                /* set the focus to the new input element */
                original_element.children("form").children(".inplace_field").focus().select();

                /* CLICK CANCEL BUTTON functionality */
                original_element.children("form").children(".inplace_cancel").click(cancelAction);

                /* CLICK SAVE BUTTON functionality */
                original_element.children("form").children(".inplace_save").click(saveAction);

                /* if cancel/save buttons should be shown, cancel blur functionality */
                if(!settings.show_buttons){
                    /* if on_blur is set to save, set the save funcion */
                    if(settings.on_blur == "save")
                        original_element.children("form").children(".inplace_field").blur(saveAction);
                    /* if on_blur is set to cancel, set the cancel funcion */
                    else
                        original_element.children("form").children(".inplace_field").blur(cancelAction);
                }

                /* hit esc key */
                $(document).keyup(function(event){
                    if (event.keyCode == 27) {
                        cancelAction();
                    }
                });

                original_element.children("form").submit(saveAction);

            }/* END- if(click_count == 1) -END */
        });
    });
};

/*
 * jQuery Corners 0.3
 * Copyright (c) 2008 David Turnbull, Steven Wittens
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 */
jQuery.fn.corners=function(C){var N="rounded_by_jQuery_corners";var V=B(C);var F=false;try{F=(document.body.style.WebkitBorderRadius!==undefined);var Y=navigator.userAgent.indexOf("Chrome");if(Y>=0){F=false}}catch(E){}var W=false;try{W=(document.body.style.MozBorderRadius!==undefined);var Y=navigator.userAgent.indexOf("Firefox");if(Y>=0&&parseInt(navigator.userAgent.substring(Y+8))<3){W=false}}catch(E){}return this.each(function(b,h){$e=jQuery(h);if($e.hasClass(N)){return }$e.addClass(N);var a=/{(.*)}/.exec(h.className);var c=a?B(a[1],V):V;var j=h.nodeName.toLowerCase();if(j=="input"){h=O(h)}if(F&&c.webkit){K(h,c)}else{if(W&&c.mozilla&&(c.sizex==c.sizey)){M(h,c)}else{var d=D(h.parentNode);var f=D(h);switch(j){case"a":case"input":Z(h,c,d,f);break;default:R(h,c,d,f);break}}}});function K(d,c){var a=""+c.sizex+"px "+c.sizey+"px";var b=jQuery(d);if(c.tl){b.css("WebkitBorderTopLeftRadius",a)}if(c.tr){b.css("WebkitBorderTopRightRadius",a)}if(c.bl){b.css("WebkitBorderBottomLeftRadius",a)}if(c.br){b.css("WebkitBorderBottomRightRadius",a)}}function M(d,c){var a=""+c.sizex+"px";var b=jQuery(d);if(c.tl){b.css("-moz-border-radius-topleft",a)}if(c.tr){b.css("-moz-border-radius-topright",a)}if(c.bl){b.css("-moz-border-radius-bottomleft",a)}if(c.br){b.css("-moz-border-radius-bottomright",a)}}function Z(k,n,l,a){var m=S("table");var i=S("tbody");m.appendChild(i);var j=S("tr");var d=S("td","top");j.appendChild(d);var h=S("tr");var c=T(k,n,S("td"));h.appendChild(c);var f=S("tr");var b=S("td","bottom");f.appendChild(b);if(n.tl||n.tr){i.appendChild(j);X(d,n,l,a,true)}i.appendChild(h);if(n.bl||n.br){i.appendChild(f);X(b,n,l,a,false)}k.appendChild(m);if(jQuery.browser.msie){m.onclick=Q}k.style.overflow="hidden"}function Q(){if(!this.parentNode.onclick){this.parentNode.click()}}function O(c){var b=document.createElement("a");b.id=c.id;b.className=c.className;if(c.onclick){b.href="javascript:";b.onclick=c.onclick}else{jQuery(c).parent("form").each(function(){b.href=this.action});b.onclick=I}var a=document.createTextNode(c.value);b.appendChild(a);c.parentNode.replaceChild(b,c);return b}function I(){jQuery(this).parent("form").each(function(){this.submit()});return false}function R(d,a,b,c){var f=T(d,a,document.createElement("div"));d.appendChild(f);if(a.tl||a.tr){X(d,a,b,c,true)}if(a.bl||a.br){X(d,a,b,c,false)}}function T(j,i,k){var b=jQuery(j);var l;while(l=j.firstChild){k.appendChild(l)}if(j.style.height){var f=parseInt(b.css("height"));k.style.height=f+"px";f+=parseInt(b.css("padding-top"))+parseInt(b.css("padding-bottom"));j.style.height=f+"px"}if(j.style.width){var a=parseInt(b.css("width"));k.style.width=a+"px";a+=parseInt(b.css("padding-left"))+parseInt(b.css("padding-right"));j.style.width=a+"px"}k.style.paddingLeft=b.css("padding-left");k.style.paddingRight=b.css("padding-right");if(i.tl||i.tr){k.style.paddingTop=U(j,i,b.css("padding-top"),true)}else{k.style.paddingTop=b.css("padding-top")}if(i.bl||i.br){k.style.paddingBottom=U(j,i,b.css("padding-bottom"),false)}else{k.style.paddingBottom=b.css("padding-bottom")}j.style.padding=0;return k}function U(f,a,d,c){if(d.indexOf("px")<0){try{console.error("%s padding not in pixels",(c?"top":"bottom"),f)}catch(b){}d=a.sizey+"px"}d=parseInt(d);if(d-a.sizey<0){try{console.error("%s padding is %ipx for %ipx corner:",(c?"top":"bottom"),d,a.sizey,f)}catch(b){}d=a.sizey}return d-a.sizey+"px"}function S(b,a){var c=document.createElement(b);c.style.border="none";c.style.borderCollapse="collapse";c.style.borderSpacing=0;c.style.padding=0;c.style.margin=0;if(a){c.style.verticalAlign=a}return c}function D(b){try{var d=jQuery.css(b,"background-color");if(d.match(/^(transparent|rgba\(0,\s*0,\s*0,\s*0\))$/i)&&b.parentNode){return D(b.parentNode)}if(d==null){return"#ffffff"}if(d.indexOf("rgb")>-1){d=A(d)}if(d.length==4){d=L(d)}return d}catch(a){return"#ffffff"}}function L(a){return"#"+a.substring(1,2)+a.substring(1,2)+a.substring(2,3)+a.substring(2,3)+a.substring(3,4)+a.substring(3,4)}function A(h){var a=255;var d="";var b;var e=/([0-9]+)[, ]+([0-9]+)[, ]+([0-9]+)/;var f=e.exec(h);for(b=1;b<4;b++){d+=("0"+parseInt(f[b]).toString(16)).slice(-2)}return"#"+d}function B(b,d){var b=b||"";var c={sizex:5,sizey:5,tl:false,tr:false,bl:false,br:false,webkit:true,mozilla:true,transparent:false};if(d){c.sizex=d.sizex;c.sizey=d.sizey;c.webkit=d.webkit;c.transparent=d.transparent;c.mozilla=d.mozilla}var a=false;var e=false;jQuery.each(b.split(" "),function(f,j){j=j.toLowerCase();var h=parseInt(j);if(h>0&&j==h+"px"){c.sizey=h;if(!a){c.sizex=h}a=true}else{switch(j){case"no-native":c.webkit=c.mozilla=false;break;case"webkit":c.webkit=true;break;case"no-webkit":c.webkit=false;break;case"mozilla":c.mozilla=true;break;case"no-mozilla":c.mozilla=false;break;case"anti-alias":c.transparent=false;break;case"transparent":c.transparent=true;break;case"top":e=c.tl=c.tr=true;break;case"right":e=c.tr=c.br=true;break;case"bottom":e=c.bl=c.br=true;break;case"left":e=c.tl=c.bl=true;break;case"top-left":e=c.tl=true;break;case"top-right":e=c.tr=true;break;case"bottom-left":e=c.bl=true;break;case"bottom-right":e=c.br=true;break}}});if(!e){if(!d){c.tl=c.tr=c.bl=c.br=true}else{c.tl=d.tl;c.tr=d.tr;c.bl=d.bl;c.br=d.br}}return c}function P(f,d,h){var e=Array(parseInt("0x"+f.substring(1,3)),parseInt("0x"+f.substring(3,5)),parseInt("0x"+f.substring(5,7)));var c=Array(parseInt("0x"+d.substring(1,3)),parseInt("0x"+d.substring(3,5)),parseInt("0x"+d.substring(5,7)));r="0"+Math.round(e[0]+(c[0]-e[0])*h).toString(16);g="0"+Math.round(e[1]+(c[1]-e[1])*h).toString(16);d="0"+Math.round(e[2]+(c[2]-e[2])*h).toString(16);return"#"+r.substring(r.length-2)+g.substring(g.length-2)+d.substring(d.length-2)}function X(f,a,b,d,c){if(a.transparent){G(f,a,b,c)}else{J(f,a,b,d,c)}}function J(k,z,p,a,n){var h,f;var l=document.createElement("div");l.style.fontSize="1px";l.style.backgroundColor=p;var b=0;for(h=1;h<=z.sizey;h++){var u,t,q;arc=Math.sqrt(1-Math.pow(1-h/z.sizey,2))*z.sizex;var c=z.sizex-Math.ceil(arc);var w=Math.floor(b);var v=z.sizex-c-w;var o=document.createElement("div");var m=l;o.style.margin="0px "+c+"px";o.style.height="1px";o.style.overflow="hidden";for(f=1;f<=v;f++){if(f==1){if(f==v){u=((arc+b)*0.5)-w}else{t=Math.sqrt(1-Math.pow(1-(c+1)/z.sizex,2))*z.sizey;u=(t-(z.sizey-h))*(arc-w-v+1)*0.5}}else{if(f==v){t=Math.sqrt(1-Math.pow((z.sizex-c-f+1)/z.sizex,2))*z.sizey;u=1-(1-(t-(z.sizey-h)))*(1-(b-w))*0.5}else{q=Math.sqrt(1-Math.pow((z.sizex-c-f)/z.sizex,2))*z.sizey;t=Math.sqrt(1-Math.pow((z.sizex-c-f+1)/z.sizex,2))*z.sizey;u=((t+q)*0.5)-(z.sizey-h)}}H(z,o,m,n,P(p,a,u));m=o;var o=m.cloneNode(false);o.style.margin="0px 1px"}H(z,o,m,n,a);b=arc}if(n){k.insertBefore(l,k.firstChild)}else{k.appendChild(l)}}function H(c,a,e,d,b){if(d&&!c.tl){a.style.marginLeft=0}if(d&&!c.tr){a.style.marginRight=0}if(!d&&!c.bl){a.style.marginLeft=0}if(!d&&!c.br){a.style.marginRight=0}a.style.backgroundColor=b;if(d){e.appendChild(a)}else{e.insertBefore(a,e.firstChild)}}function G(c,o,l,h){var f=document.createElement("div");f.style.fontSize="1px";var a=document.createElement("div");a.style.overflow="hidden";a.style.height="1px";a.style.borderColor=l;a.style.borderStyle="none solid";var m=o.sizex-1;var j=o.sizey-1;if(!j){j=1}for(var b=0;b<o.sizey;b++){var n=m-Math.floor(Math.sqrt(1-Math.pow(1-b/j,2))*m);if(b==2&&o.sizex==6&&o.sizey==6){n=2}var k=a.cloneNode(false);k.style.borderWidth="0 "+n+"px";if(h){k.style.borderWidth="0 "+(o.tr?n:0)+"px 0 "+(o.tl?n:0)+"px"}else{k.style.borderWidth="0 "+(o.br?n:0)+"px 0 "+(o.bl?n:0)+"px"}h?f.appendChild(k):f.insertBefore(k,f.firstChild)}if(h){c.insertBefore(f,c.firstChild)}else{c.appendChild(f)}}};


/*
 ### jQuery Multiple File Upload Plugin v1.31 - 2009-01-17 ###
 * Home: http://www.fyneworks.com/jquery/multiple-file-upload/
 * Code: http://code.google.com/p/jquery-multifile-plugin/
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 ###
*/
 
 // extend jQuery - $.MultiFile hook
 $.extend($, {
  MultiFile: function( o /* Object */ ){
   //return $("INPUT[type='file'].multi").MultiFile(o);
   return $("input:file.multi").MultiFile(o);
  }
 });
 
 //===
 
 // extend $.MultiFile - default options
 $.extend($.MultiFile, {
  options: {
   accept: '', max: -1,
   // error handling function
   error: function(s){
    if($.blockUI){
     $.blockUI({
      message: s.replace(/\n/gi,'<br/>'),
      css: { 
       border:'none', padding:'15px', size:'12.0pt',
       backgroundColor:'#900', color:'#fff',
       opacity:'.8','-webkit-border-radius': '10px','-moz-border-radius': '10px'
      }
     });
     window.setTimeout($.unblockUI, 2000);
    }
    else{
     alert(s);
    }
   },
   // namePattern: $name/$id (from master element), $i (slave count), $g (group count)
   namePattern: '$name',
   // STRING: collection lets you show messages in different languages
   STRING: {
    remove:'x',
    denied:'You cannot select a $ext file.\nTry again...',
    file:'$file',
    selected:'File selected: $file',
    duplicate:'This file has already been selected:\n$file'
   }
  }
 });
 
 //===
 
 // extend $.MultiFile - global methods
 $.extend($.MultiFile, {
  
  
  /**
   * This utility makes it easy to disable all 'empty' file elements in the document before submitting a form.
   * It marks the affected elements so they can be easily re-enabled after the form submission or validation.
   *
   * Returns a jQuery collection of all affected elements.
   *
   * @name disableEmpty
   * @type jQuery
   * @cat Plugins/Multifile
   * @author Diego A. (http://www.fyneworks.com/)
   *
   * @example $.MultiFile.disableEmpty();
   * @param String class (optional) A string specifying a class to be applied to all affected elements - Default: 'mfD'.
   */
  disableEmpty: function(klass){
   var o = [];
   $('input:file').each(function(){ if($(this).val()=='') o[o.length] = this; });
   return $(o).each(function(){ this.disabled = true }).addClass(klass || 'mfD');
  },
  
  
 /**
  * This method re-enables 'empty' file elements that were disabled (and marked) with the $.MultiFile.disableEmpty method.
  *
  * Returns a jQuery collection of all affected elements.
  *
  * @name reEnableEmpty
  * @type jQuery
  * @cat Plugins/Multifile
  * @author Diego A. (http://www.fyneworks.com/)
  *
  * @example $.MultiFile.reEnableEmpty();
  * @param String klass (optional) A string specifying the class that was used to mark affected elements - Default: 'mfD'.
  */
  reEnableEmpty: function(klass){
   klass = klass || 'mfD';
   return $('input:file.'+klass).removeClass(klass).each(function(){ this.disabled = false });
  },
  
  
 /**
  * This method will intercept other jQuery plugins and disable empty file input elements prior to form submission
  *
  * @name intercept
  * @cat Plugins/Multifile
  * @author Diego A. (http://www.fyneworks.com/)
  *
  * @example $.MultiFile.intercept();
  * @param Array methods (optional) Array of method names to be intercepted
  */
  autoIntercept: [ 'submit', 'ajaxSubmit', 'validate' /* array of methods to intercept */ ],
  intercepted: {},
  intercept: function(methods, context, args){
   var method, value; args = args || [];
   if(args.constructor.toString().indexOf("Array")<0) args = [ args ];
   if(typeof(methods)=='function'){
    $.MultiFile.disableEmpty();
    value = methods.apply(context || window, args);
    $.MultiFile.reEnableEmpty();
    return value;
   };
   if(methods.constructor.toString().indexOf("Array")<0) methods = [methods];
   for(var i=0;i<methods.length;i++){
    method = methods[i]+''; // make sure that we have a STRING
    if(method) (function(method){ // make sure that method is ISOLATED for the interception
     $.MultiFile.intercepted[method] = $.fn[method] || function(){};
     $.fn[method] = function(){
      $.MultiFile.disableEmpty();
      value = $.MultiFile.intercepted[method].apply(this, arguments);
      $.MultiFile.reEnableEmpty();
      return value;
     }; // interception
    })(method); // MAKE SURE THAT method IS ISOLATED for the interception
   };// for each method
  }
 });
 
 //===
 
 // extend jQuery function library
 $.extend($.fn, {
   
			// Use this function to clear values of file inputs
			// But this doesn't always work: $(element).val('').attr('value', '')[0].value = '';
			reset: function(){ return this.each(function(){ try{ this.reset(); }catch(e){} }); },
    
   // MultiFile function
   MultiFile: function( options /* Object */ ){
    
    //### http://plugins.jquery.com/node/1363
    // utility method to integrate this plugin with others...
    if($.MultiFile.autoIntercept){
     $.MultiFile.intercept( $.MultiFile.autoIntercept /* array of methods to intercept */ );
     $.MultiFile.autoIntercept = null; /* only run this once */
    };
    
    //===
    
    // Bind to each element in current jQuery object
    return $(this).each(function(group_count){
     if(this._MultiFile) return; this._MultiFile = true;
     
       // BUG 1251 FIX: http://plugins.jquery.com/project/comments/add/1251
       // variable group_count would repeat itself on multiple calls to the plugin.
       // this would cause a conflict with multiple elements
       // changes scope of variable to global so id will be unique over n calls
       window.MultiFile = (window.MultiFile || 0) + 1;
       group_count = window.MultiFile;
       
       // Copy parent attributes - Thanks to Jonas Wagner
       // we will use this one to create new input elements
       var MF = {e:this, E:$(this), clone:$(this).clone()};
       
       //===
       
       //# USE CONFIGURATION
       if(typeof options=='number') options = {max:options};
       if(typeof options=='string') options = {accept:options};
       var o = $.extend({},
        $.MultiFile.options,
        options || {},
        ($.meta ? MF.E.data()/*NEW metadata plugin*/ :
        ($.metadata ? MF.E.metadata()/*OLD metadata plugin*/ : 
        null/*metadata plugin not available*/)) || {}
       );
       // limit number of files that can be selected?
       if(!(o.max>0) /*IsNull(MF.max)*/){
        o.max = MF.E.attr('maxlength');
        if(!(o.max>0) /*IsNull(MF.max)*/){
         o.max = (String(MF.e.className.match(/\b(max|limit)\-([0-9]+)\b/gi) || ['']).match(/[0-9]+/gi) || [''])[0];
         if(!(o.max>0)) o.max = -1;
         else           o.max = String(o.max).match(/[0-9]+/gi)[0];
        }
       };
       o.max = new Number(o.max);
       // limit extensions?
       o.accept = o.accept || MF.E.attr('accept') || '';
       if(!o.accept){
        o.accept = (MF.e.className.match(/\b(accept\-[\w\|]+)\b/gi)) || '';
        o.accept = new String(o.accept).replace(/^(accept|ext)\-/i,'');
       };
       
       //===
       
       // APPLY CONFIGURATION
       $.extend(MF, o || {});
       MF.STRING = $.extend({},$.MultiFile.options.STRING,MF.STRING);
       
       //===
       
       //#########################################
       // PRIVATE PROPERTIES/METHODS
       $.extend(MF, {
        n: 0, // How many elements are currently selected?
        slaves: [], files: [],
        instanceKey: MF.e.id || 'MultiFile'+String(group_count), // Instance Key?
        generateID: function(z){ return MF.instanceKey + (z>0 ?'_F'+String(z):''); },
        trigger: function(event, element){
         var handler = MF[event], value = $(element).attr('value');
         if(handler){
          var returnValue = handler(element, value, MF);
          if( returnValue!=null ) return returnValue;
         }
         return true;
        }
       });
       
       //===
       
       // Setup dynamic regular expression for extension validation
       // - thanks to John-Paul Bader: http://smyck.de/2006/08/11/javascript-dynamic-regular-expresions/
       if(String(MF.accept).length>1){
        MF.rxAccept = new RegExp('\\.('+(MF.accept?MF.accept:'')+')$','gi');
       };
       
       //===
       
       // Create wrapper to hold our file list
       MF.wrapID = MF.instanceKey+'_wrap'; // Wrapper ID?
       MF.E.wrap('<div id="'+MF.wrapID+'"></div>');
       MF.wrapper = $('#'+MF.wrapID+'');
       
       //===
       
       // MF MUST have a name - default: file1[], file2[], file3[]
       MF.e.name = MF.e.name || 'file'+ group_count +'[]';
       
       //===
       
							if(!MF.list){
								// Create a wrapper for the list
								// * OPERA BUG: NO_MODIFICATION_ALLOWED_ERR ('list' is a read-only property)
								// this change allows us to keep the files in the order they were selected
								MF.wrapper.append( '<span id="'+MF.wrapID+'_list"></span>' );
								MF.list = $('#'+MF.wrapID+'_list');
							};
       MF.list = $(MF.list);
							
       //===
       
       // Bind a new element
       MF.addSlave = function( slave, slave_count ){
        // Keep track of how many elements have been displayed
        MF.n++;
        // Add reference to master element
        slave.MF = MF;
        // Count slaves
        slave.i = slave_count;
        
        // BUG FIX: http://plugins.jquery.com/node/1495
        // Clear identifying properties from clones
        if(slave.i>0) slave.id = slave.name = null;
        
        // Define element's ID and name (upload components need this!)
        slave.id = slave.id || MF.generateID(slave.i);
        
        //slave.name = (slave.name || MF.E.attr('name') || 'file');// + (slave.i>0?slave.i:''); // same name as master element
        // 2008-Apr-29: New customizable naming convention (see url below)
        // http://groups.google.com/group/jquery-dev/browse_frm/thread/765c73e41b34f924#
        slave.name = String(MF.namePattern
         /*master name*/.replace(/\$name/gi,MF.E.attr('name'))
         /*master id  */.replace(/\$id/gi,  MF.E.attr('id'))
         /*group count*/.replace(/\$g/gi,   (group_count>0?group_count:''))
         /*slave count*/.replace(/\$i/gi,   (slave_count>0?slave_count:''))
        );
        
        // Clear value
        $(slave).val('').attr('value','')[0].value = '';
        
        // If we've reached maximum number, disable input slave
        if( (MF.max > 0) && ((MF.n-1) > (MF.max)) )//{ // MF.n Starts at 1, so subtract 1 to find true count
         slave.disabled = true;
        //};
        
        // Remember most recent slave
        MF.current = MF.slaves[slave.i] = slave;
        
        // now let's use jQuery
        slave = $(slave);
        
        // Triggered when a file is selected
        $(slave).change(function(){
          
          // Lose focus to stop IE7 firing onchange again
          $(this).blur();
          
          //# Trigger Event! onFileSelect
          if(!MF.trigger('onFileSelect', this, MF)) return false;
          //# End Event!
          
          //# Retrive value of selected file from element
          var ERROR = '', v = String(this.value || ''/*.attr('value)*/);
          
          // check extension
          if(MF.accept && v && !v.match(MF.rxAccept))//{
            ERROR = MF.STRING.denied.replace('$ext', String(v.match(/\.\w{1,4}$/gi)));
           //}
          //};
          
          // Disallow duplicates
										for(var f in MF.slaves)//{
           if(MF.slaves[f] && MF.slaves[f]!=this)//{
  										//console.log(MF.slaves[f],MF.slaves[f].value);
            if(MF.slaves[f].value==v)//{
             ERROR = MF.STRING.duplicate.replace('$file', v.match(/[^\/\\]+$/gi));
            //};
           //};
          //};
          
          // Create a new file input element
          //var newEle = $('<input name="'+(MF.E.attr('name') || '')+'" type="file"/>');
          var newEle = $(MF.clone).clone();// Copy parent attributes - Thanks to Jonas Wagner
          //# Let's remember which input we've generated so
          // we can disable the empty ones before submission
          // See: http://plugins.jquery.com/node/1495
          newEle.addClass('MultiFile');
          
          // Handle error
          if(ERROR!=''){
            // Handle error
            MF.error(ERROR);
            
            // Clear element value (DOES NOT WORK in some browsers)
            //slave.reset().val('').attr('value', '')[0].value = '';
            
            // 2007-06-24: BUG FIX - Thanks to Adrian Wr?bel <adrian [dot] wrobel [at] gmail.com>
            // Ditch the trouble maker and add a fresh new element
            MF.n--;
            MF.addSlave(newEle[0], this.i);
            slave.parent().prepend(newEle);
            slave.remove();
            return false;
          };
          
          // Hide this element (NB: display:none is evil!)
          $(this).css({ position:'absolute', top: '-3000px' });
          
          // Add new element to the form
          //MF.list.before(newEle);//.append(newEle);
          MF.wrapper.prepend(newEle);//.append(newEle);
          
          // Update list
          MF.addToList( this );
          
          // Bind functionality
          MF.addSlave( newEle[0], this.i+1 );
          
          //# Trigger Event! afterFileSelect
          if(!MF.trigger('afterFileSelect', this, MF)) return false;
          //# End Event!
          
        }); // slave.change()
        
       };// MF.addSlave
       // Bind a new element
       
       
       
       // Add a new file to the list
       MF.addToList = function( slave ){
        
        //# Trigger Event! onFileAppend
        if(!MF.trigger('onFileAppend', slave, MF)) return false;
        //# End Event!
        
        // Create label elements
        var
         r = $('<div class="in_queue"></div>'),
         v = String(slave.value || ''/*.attr('value)*/),
         a = $('<span class="file" title="'+MF.STRING.selected.replace('$file', v)+'">'+MF.STRING.file.replace('$file', v.match(/[^\/\\]+$/gi)[0])+'</span>'),
         b = $('<a href="#'+MF.wrapID+'">'+MF.STRING.remove+'</a>'),
				 c = $('<div class="clearer"></div>');
        
        // Insert label
        MF.list.append(
         r.append(a, ' ',b, c)//.prepend(slave.i+': ')
        );
        
        b.click(function(){
         
          //# Trigger Event! onFileRemove
          if(!MF.trigger('onFileRemove', slave, MF)) return false;
          //# End Event!
          
          MF.n--;
          MF.current.disabled = false;
          
          // Remove element, remove label, point to current
										MF.slaves[slave.i] = null;
										$(slave).remove();
										$(this).parent().remove();
          
          // Show most current element again (move into view) and clear selection
          $(MF.current).css({ position:'', top: '' });
										$(MF.current).reset().val('').attr('value', '')[0].value = '';
          
          //# Trigger Event! afterFileRemove
          if(!MF.trigger('afterFileRemove', slave, MF)) return false;
          //# End Event!
										
          return false;
        });
        
        //# Trigger Event! afterFileAppend
        if(!MF.trigger('afterFileAppend', slave, MF)) return false;
        //# End Event!
        
       }; // MF.addToList
       // Add element to selected files list
       
       
       
       // Bind functionality to the first element
       if(!MF.MF) MF.addSlave(MF.e, 0);
       
       // Increment control count
       //MF.I++; // using window.MultiFile
       MF.n++;
       
    });
    // each element
   
   }
   // MultiFile function
 
 });
 // extend jQuery function library
 
 
 
 /*
  ### Default implementation ###
  The plugin will attach itself to file inputs
  with the class 'multi' when the page loads
 */
// $(function(){ $.MultiFile() });

