
/*!
 * jQuery Form Plugin
 * version: 2.52 (07-DEC-2010)
 * @requires jQuery v1.3.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(b){function q(){if(b.fn.ajaxSubmit.debug){var a="[jquery.form] "+Array.prototype.join.call(arguments,"");if(window.console&&window.console.log)window.console.log(a);else window.opera&&window.opera.postError&&window.opera.postError(a)}}b.fn.ajaxSubmit=function(a){function f(){function t(){var o=i.attr("target"),m=i.attr("action");l.setAttribute("target",u);l.getAttribute("method")!="POST"&&l.setAttribute("method","POST");l.getAttribute("action")!=e.url&&l.setAttribute("action",e.url);e.skipEncodingOverride|| i.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"});e.timeout&&setTimeout(function(){F=true;s()},e.timeout);var v=[];try{if(e.extraData)for(var w in e.extraData)v.push(b('<input type="hidden" name="'+w+'" value="'+e.extraData[w]+'" />').appendTo(l)[0]);r.appendTo("body");r.data("form-plugin-onload",s);l.submit()}finally{l.setAttribute("action",m);o?l.setAttribute("target",o):i.removeAttr("target");b(v).remove()}}function s(){if(!G){r.removeData("form-plugin-onload");var o=true; try{if(F)throw"timeout";p=x.contentWindow?x.contentWindow.document:x.contentDocument?x.contentDocument:x.document;var m=e.dataType=="xml"||p.XMLDocument||b.isXMLDoc(p);q("isXml="+m);if(!m&&window.opera&&(p.body==null||p.body.innerHTML==""))if(--K){q("requeing onLoad callback, DOM not available");setTimeout(s,250);return}G=true;j.responseText=p.documentElement?p.documentElement.innerHTML:null;j.responseXML=p.XMLDocument?p.XMLDocument:p;j.getResponseHeader=function(L){return{"content-type":e.dataType}[L]}; var v=/(json|script)/.test(e.dataType);if(v||e.textarea){var w=p.getElementsByTagName("textarea")[0];if(w)j.responseText=w.value;else if(v){var H=p.getElementsByTagName("pre")[0],I=p.getElementsByTagName("body")[0];if(H)j.responseText=H.textContent;else if(I)j.responseText=I.innerHTML}}else if(e.dataType=="xml"&&!j.responseXML&&j.responseText!=null)j.responseXML=C(j.responseText);J=b.httpData(j,e.dataType)}catch(D){q("error caught:",D);o=false;j.error=D;b.handleError(e,j,"error",D)}if(j.aborted){q("upload aborted"); o=false}if(o){e.success.call(e.context,J,"success",j);y&&b.event.trigger("ajaxSuccess",[j,e])}y&&b.event.trigger("ajaxComplete",[j,e]);y&&!--b.active&&b.event.trigger("ajaxStop");if(e.complete)e.complete.call(e.context,j,o?"success":"error");setTimeout(function(){r.removeData("form-plugin-onload");r.remove();j.responseXML=null},100)}}function C(o,m){if(window.ActiveXObject){m=new ActiveXObject("Microsoft.XMLDOM");m.async="false";m.loadXML(o)}else m=(new DOMParser).parseFromString(o,"text/xml");return m&& m.documentElement&&m.documentElement.tagName!="parsererror"?m:null}var l=i[0];if(b(":input[name=submit],:input[id=submit]",l).length)alert('Error: Form elements must not have name or id of "submit".');else{var e=b.extend(true,{},b.ajaxSettings,a);e.context=e.context||e;var u="jqFormIO"+(new Date).getTime(),E="_"+u;window[E]=function(){var o=r.data("form-plugin-onload");if(o){o();window[E]=undefined;try{delete window[E]}catch(m){}}};var r=b('<iframe id="'+u+'" name="'+u+'" src="'+e.iframeSrc+'" onload="window[\'_\'+this.id]()" />'), x=r[0];r.css({position:"absolute",top:"-1000px",left:"-1000px"});var j={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(){this.aborted=1;r.attr("src",e.iframeSrc)}},y=e.global;y&&!b.active++&&b.event.trigger("ajaxStart");y&&b.event.trigger("ajaxSend",[j,e]);if(e.beforeSend&&e.beforeSend.call(e.context,j,e)===false)e.global&&b.active--;else if(!j.aborted){var G=false, F=0,z=l.clk;if(z){var A=z.name;if(A&&!z.disabled){e.extraData=e.extraData||{};e.extraData[A]=z.value;if(z.type=="image"){e.extraData[A+".x"]=l.clk_x;e.extraData[A+".y"]=l.clk_y}}}e.forceSync?t():setTimeout(t,10);var J,p,K=50}}}if(!this.length){q("ajaxSubmit: skipping submit process - no element selected");return this}if(typeof a=="function")a={success:a};var d=this.attr("action");if(d=typeof d==="string"?b.trim(d):"")d=(d.match(/^([^#]+)/)||[])[1];d=d||window.location.href||"";a=b.extend(true,{url:d, type:this.attr("method")||"GET",iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},a);d={};this.trigger("form-pre-serialize",[this,a,d]);if(d.veto){q("ajaxSubmit: submit vetoed via form-pre-serialize trigger");return this}if(a.beforeSerialize&&a.beforeSerialize(this,a)===false){q("ajaxSubmit: submit aborted via beforeSerialize callback");return this}var c,h,g=this.formToArray(a.semantic);if(a.data){a.extraData=a.data;for(c in a.data)if(a.data[c]instanceof Array)for(var k in a.data[c])g.push({name:c, value:a.data[c][k]});else{h=a.data[c];h=b.isFunction(h)?h():h;g.push({name:c,value:h})}}if(a.beforeSubmit&&a.beforeSubmit(g,this,a)===false){q("ajaxSubmit: submit aborted via beforeSubmit callback");return this}this.trigger("form-submit-validate",[g,this,a,d]);if(d.veto){q("ajaxSubmit: submit vetoed via form-submit-validate trigger");return this}c=b.param(g);if(a.type.toUpperCase()=="GET"){a.url+=(a.url.indexOf("?")>=0?"&":"?")+c;a.data=null}else a.data=c;var i=this,n=[];a.resetForm&&n.push(function(){i.resetForm()}); a.clearForm&&n.push(function(){i.clearForm()});if(!a.dataType&&a.target){var B=a.success||function(){};n.push(function(t){var s=a.replaceTarget?"replaceWith":"html";b(a.target)[s](t).each(B,arguments)})}else a.success&&n.push(a.success);a.success=function(t,s,C){for(var l=a.context||a,e=0,u=n.length;e<u;e++)n[e].apply(l,[t,s,C||i,i])};c=b("input:file",this).length>0;k=i.attr("enctype")=="multipart/form-data"||i.attr("encoding")=="multipart/form-data";if(a.iframe!==false&&(c||a.iframe||k))a.closeKeepAlive? b.get(a.closeKeepAlive,f):f();else b.ajax(a);this.trigger("form-submit-notify",[this,a]);return this};b.fn.ajaxForm=function(a){if(this.length===0){var f={s:this.selector,c:this.context};if(!b.isReady&&f.s){q("DOM not ready, queuing ajaxForm");b(function(){b(f.s,f.c).ajaxForm(a)});return this}q("terminating; zero elements found by selector"+(b.isReady?"":" (DOM not ready)"));return this}return this.ajaxFormUnbind().bind("submit.form-plugin",function(d){if(!d.isDefaultPrevented()){d.preventDefault(); b(this).ajaxSubmit(a)}}).bind("click.form-plugin",function(d){var c=d.target,h=b(c);if(!h.is(":submit,input:image")){c=h.closest(":submit");if(c.length==0)return;c=c[0]}var g=this;g.clk=c;if(c.type=="image")if(d.offsetX!=undefined){g.clk_x=d.offsetX;g.clk_y=d.offsetY}else if(typeof b.fn.offset=="function"){h=h.offset();g.clk_x=d.pageX-h.left;g.clk_y=d.pageY-h.top}else{g.clk_x=d.pageX-c.offsetLeft;g.clk_y=d.pageY-c.offsetTop}setTimeout(function(){g.clk=g.clk_x=g.clk_y=null},100)})};b.fn.ajaxFormUnbind= function(){return this.unbind("submit.form-plugin click.form-plugin")};b.fn.formToArray=function(a){var f=[];if(this.length===0)return f;var d=this[0],c=a?d.getElementsByTagName("*"):d.elements;if(!c)return f;var h,g,k,i,n,B;h=0;for(n=c.length;h<n;h++){g=c[h];if(k=g.name)if(a&&d.clk&&g.type=="image"){if(!g.disabled&&d.clk==g){f.push({name:k,value:b(g).val()});f.push({name:k+".x",value:d.clk_x},{name:k+".y",value:d.clk_y})}}else if((i=b.fieldValue(g,true))&&i.constructor==Array){g=0;for(B=i.length;g< B;g++)f.push({name:k,value:i[g]})}else i!==null&&typeof i!="undefined"&&f.push({name:k,value:i})}if(!a&&d.clk){a=b(d.clk);c=a[0];if((k=c.name)&&!c.disabled&&c.type=="image"){f.push({name:k,value:a.val()});f.push({name:k+".x",value:d.clk_x},{name:k+".y",value:d.clk_y})}}return f};b.fn.formSerialize=function(a){return b.param(this.formToArray(a))};b.fn.fieldSerialize=function(a){var f=[];this.each(function(){var d=this.name;if(d){var c=b.fieldValue(this,a);if(c&&c.constructor==Array)for(var h=0,g=c.length;h< g;h++)f.push({name:d,value:c[h]});else c!==null&&typeof c!="undefined"&&f.push({name:this.name,value:c})}});return b.param(f)};b.fn.fieldValue=function(a){for(var f=[],d=0,c=this.length;d<c;d++){var h=b.fieldValue(this[d],a);h===null||typeof h=="undefined"||h.constructor==Array&&!h.length||(h.constructor==Array?b.merge(f,h):f.push(h))}return f};b.fieldValue=function(a,f){var d=a.name,c=a.type,h=a.tagName.toLowerCase();if(f===undefined)f=true;if(f&&(!d||a.disabled||c=="reset"||c=="button"||(c=="checkbox"|| c=="radio")&&!a.checked||(c=="submit"||c=="image")&&a.form&&a.form.clk!=a||h=="select"&&a.selectedIndex==-1))return null;if(h=="select"){var g=a.selectedIndex;if(g<0)return null;d=[];h=a.options;var k=(c=c=="select-one")?g+1:h.length;for(g=c?g:0;g<k;g++){var i=h[g];if(i.selected){var n=i.value;n||(n=i.attributes&&i.attributes.value&&!i.attributes.value.specified?i.text:i.value);if(c)return n;d.push(n)}}return d}return b(a).val()};b.fn.clearForm=function(){return this.each(function(){b("input,select,textarea", this).clearFields()})};b.fn.clearFields=b.fn.clearInputs=function(){return this.each(function(){var a=this.type,f=this.tagName.toLowerCase();if(a=="text"||a=="password"||f=="textarea")this.value="";else if(a=="checkbox"||a=="radio")this.checked=false;else if(f=="select")this.selectedIndex=-1})};b.fn.resetForm=function(){return this.each(function(){if(typeof this.reset=="function"||typeof this.reset=="object"&&!this.reset.nodeType)this.reset()})};b.fn.enable=function(a){if(a===undefined)a=true;return this.each(function(){this.disabled= !a})};b.fn.selected=function(a){if(a===undefined)a=true;return this.each(function(){var f=this.type;if(f=="checkbox"||f=="radio")this.checked=a;else if(this.tagName.toLowerCase()=="option"){f=b(this).parent("select");a&&f[0]&&f[0].type=="select-one"&&f.find("option").selected(false);this.selected=a}})}})(jQuery);;
(function ($) {

/**
 * A progressbar object. Initialized with the given id. Must be inserted into
 * the DOM afterwards through progressBar.element.
 *
 * method is the function which will perform the HTTP request to get the
 * progress bar state. Either "GET" or "POST".
 *
 * e.g. pb = new progressBar('myProgressBar');
 *      some_element.appendChild(pb.element);
 */
Drupal.progressBar = function (id, updateCallback, method, errorCallback) {
  var pb = this;
  this.id = id;
  this.method = method || 'GET';
  this.updateCallback = updateCallback;
  this.errorCallback = errorCallback;

  // The WAI-ARIA setting aria-live="polite" will announce changes after users
  // have completed their current activity and not interrupt the screen reader.
  this.element = $('<div class="progress" aria-live="polite"></div>').attr('id', id);
  this.element.html('<div class="bar"><div class="filled"></div></div>' +
                    '<div class="percentage"></div>' +
                    '<div class="message">&nbsp;</div>');
};

/**
 * Set the percentage and status message for the progressbar.
 */
Drupal.progressBar.prototype.setProgress = function (percentage, message) {
  if (percentage >= 0 && percentage <= 100) {
    $('div.filled', this.element).css('width', percentage + '%');
    $('div.percentage', this.element).html(percentage + '%');
  }
  $('div.message', this.element).html(message);
  if (this.updateCallback) {
    this.updateCallback(percentage, message, this);
  }
};

/**
 * Start monitoring progress via Ajax.
 */
Drupal.progressBar.prototype.startMonitoring = function (uri, delay) {
  this.delay = delay;
  this.uri = uri;
  this.sendPing();
};

/**
 * Stop monitoring progress via Ajax.
 */
Drupal.progressBar.prototype.stopMonitoring = function () {
  clearTimeout(this.timer);
  // This allows monitoring to be stopped from within the callback.
  this.uri = null;
};

/**
 * Request progress data from server.
 */
Drupal.progressBar.prototype.sendPing = function () {
  if (this.timer) {
    clearTimeout(this.timer);
  }
  if (this.uri) {
    var pb = this;
    // When doing a post request, you need non-null data. Otherwise a
    // HTTP 411 or HTTP 406 (with Apache mod_security) error may result.
    $.ajax({
      type: this.method,
      url: this.uri,
      data: '',
      dataType: 'json',
      success: function (progress) {
        // Display errors.
        if (progress.status == 0) {
          pb.displayError(progress.data);
          return;
        }
        // Update display.
        pb.setProgress(progress.percentage, progress.message);
        // Schedule next timer.
        pb.timer = setTimeout(function () { pb.sendPing(); }, pb.delay);
      },
      error: function (xmlhttp) {
        pb.displayError(Drupal.ajaxError(xmlhttp, pb.uri));
      }
    });
  }
};

/**
 * Display errors on the page.
 */
Drupal.progressBar.prototype.displayError = function (string) {
  var error = $('<div class="messages error"></div>').html(string);
  $(this.element).before(error).hide();

  if (this.errorCallback) {
    this.errorCallback(this);
  }
};

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

/**
 * Provides Ajax page updating via jQuery $.ajax (Asynchronous JavaScript and XML).
 *
 * Ajax is a method of making a request via JavaScript while viewing an HTML
 * page. The request returns an array of commands encoded in JSON, which is
 * then executed to make any changes that are necessary to the page.
 *
 * Drupal uses this file to enhance form elements with #ajax['path'] and
 * #ajax['wrapper'] properties. If set, this file will automatically be included
 * to provide Ajax capabilities.
 */

Drupal.ajax = Drupal.ajax || {};

/**
 * Attaches the Ajax behavior to each Ajax form element.
 */
Drupal.behaviors.AJAX = {
  attach: function (context, settings) {
    // Load all Ajax behaviors specified in the settings.
    for (var base in settings.ajax) {
      if (!$('#' + base + '.ajax-processed').length) {
        var element_settings = settings.ajax[base];

        if (typeof element_settings.selector == 'undefined') {
          element_settings.selector = '#' + base;
        }
        $(element_settings.selector).each(function () {
          element_settings.element = this;
          Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
        });

        $('#' + base).addClass('ajax-processed');
      }
    }

    // Bind Ajax behaviors to all items showing the class.
    $('.use-ajax:not(.ajax-processed)').addClass('ajax-processed').each(function () {
      var element_settings = {};
      // Clicked links look better with the throbber than the progress bar.
      element_settings.progress = { 'type': 'throbber' };

      // For anchor tags, these will go to the target of the anchor rather
      // than the usual location.
      if ($(this).attr('href')) {
        element_settings.url = $(this).attr('href');
        element_settings.event = 'click';
      }
      var base = $(this).attr('id');
      Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
    });

    // This class means to submit the form to the action using Ajax.
    $('.use-ajax-submit:not(.ajax-processed)').addClass('ajax-processed').each(function () {
      var element_settings = {};

      // Ajax submits specified in this manner automatically submit to the
      // normal form action.
      element_settings.url = $(this.form).attr('action');
      // Form submit button clicks need to tell the form what was clicked so
      // it gets passed in the POST request.
      element_settings.setClick = true;
      // Form buttons use the 'click' event rather than mousedown.
      element_settings.event = 'click';
      // Clicked form buttons look better with the throbber than the progress bar.
      element_settings.progress = { 'type': 'throbber' };

      var base = $(this).attr('id');
      Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
    });
  }
};

/**
 * Ajax object.
 *
 * All Ajax objects on a page are accessible through the global Drupal.ajax
 * object and are keyed by the submit button's ID. You can access them from
 * your module's JavaScript file to override properties or functions.
 *
 * For example, if your Ajax enabled button has the ID 'edit-submit', you can
 * redefine the function that is called to insert the new content like this
 * (inside a Drupal.behaviors attach block):
 * @code
 *    Drupal.behaviors.myCustomAJAXStuff = {
 *      attach: function (context, settings) {
 *        Drupal.ajax['edit-submit'].commands.insert = function (ajax, response, status) {
 *          new_content = $(response.data);
 *          $('#my-wrapper').append(new_content);
 *          alert('New content was appended to #my-wrapper');
 *        }
 *      }
 *    };
 * @endcode
 */
Drupal.ajax = function (base, element, element_settings) {
  var defaults = {
    url: 'system/ajax',
    event: 'mousedown',
    keypress: true,
    selector: '#' + base,
    effect: 'none',
    speed: 'none',
    method: 'replaceWith',
    progress: {
      type: 'throbber',
      message: Drupal.t('Please wait...')
    },
    submit: {
      'js': true
    }
  };

  $.extend(this, defaults, element_settings);

  this.element = element;
  this.element_settings = element_settings;

  // Replacing 'nojs' with 'ajax' in the URL allows for an easy method to let
  // the server detect when it needs to degrade gracefully.
  // There are five scenarios to check for:
  // 1. /nojs/
  // 2. /nojs$ - The end of a URL string.
  // 3. /nojs? - Followed by a query (with clean URLs enabled).
  //      E.g.: path/nojs?destination=foobar
  // 4. /nojs& - Followed by a query (without clean URLs enabled).
  //      E.g.: ?q=path/nojs&destination=foobar
  // 5. /nojs# - Followed by a fragment.
  //      E.g.: path/nojs#myfragment
  this.url = element_settings.url.replace(/\/nojs(\/|$|\?|&|#)/g, '/ajax$1');
  this.wrapper = '#' + element_settings.wrapper;

  // If there isn't a form, jQuery.ajax() will be used instead, allowing us to
  // bind Ajax to links as well.
  if (this.element.form) {
    this.form = $(this.element.form);
  }

  // Set the options for the ajaxSubmit function.
  // The 'this' variable will not persist inside of the options object.
  var ajax = this;
  ajax.options = {
    url: ajax.url,
    data: ajax.submit,
    beforeSerialize: function (element_settings, options) {
      return ajax.beforeSerialize(element_settings, options);
    },
    beforeSubmit: function (form_values, element_settings, options) {
      ajax.ajaxing = true;
      return ajax.beforeSubmit(form_values, element_settings, options);
    },
    beforeSend: function (xmlhttprequest, options) {
      ajax.ajaxing = true;
      return ajax.beforeSend(xmlhttprequest, options);
    },
    success: function (response, status) {
      // Sanity check for browser support (object expected).
      // When using iFrame uploads, responses must be returned as a string.
      if (typeof response == 'string') {
        response = $.parseJSON(response);
      }
      return ajax.success(response, status);
    },
    complete: function (response, status) {
      ajax.ajaxing = false;
      if (status == 'error' || status == 'parsererror') {
        return ajax.error(response, ajax.url);
      }
    },
    dataType: 'json',
    type: 'POST'
  };

  // Bind the ajaxSubmit function to the element event.
  $(ajax.element).bind(element_settings.event, function (event) {
    return ajax.eventResponse(this, event);
  });

  // If necessary, enable keyboard submission so that Ajax behaviors
  // can be triggered through keyboard input as well as e.g. a mousedown
  // action.
  if (element_settings.keypress) {
    $(ajax.element).keypress(function (event) {
      return ajax.keypressResponse(this, event);
    });
  }

  // If necessary, prevent the browser default action of an additional event.
  // For example, prevent the browser default action of a click, even if the
  // AJAX behavior binds to mousedown.
  if (element_settings.prevent) {
    $(ajax.element).bind(element_settings.prevent, false);
  }
};

/**
 * Handle a key press.
 *
 * The Ajax object will, if instructed, bind to a key press response. This
 * will test to see if the key press is valid to trigger this event and
 * if it is, trigger it for us and prevent other keypresses from triggering.
 * In this case we're handling RETURN and SPACEBAR keypresses (event codes 13
 * and 32. RETURN is often used to submit a form when in a textfield, and 
 * SPACE is often used to activate an element without submitting. 
 */
Drupal.ajax.prototype.keypressResponse = function (element, event) {
  // Create a synonym for this to reduce code confusion.
  var ajax = this;

  // Detect enter key and space bar and allow the standard response for them,
  // except for form elements of type 'text' and 'textarea', where the 
  // spacebar activation causes inappropriate activation if #ajax['keypress'] is 
  // TRUE. On a text-type widget a space should always be a space.
  if (event.which == 13 || (event.which == 32 && element.type != 'text' && element.type != 'textarea')) {
    $(ajax.element_settings.element).trigger(ajax.element_settings.event);
    return false;
  }
};

/**
 * Handle an event that triggers an Ajax response.
 *
 * When an event that triggers an Ajax response happens, this method will
 * perform the actual Ajax call. It is bound to the event using
 * bind() in the constructor, and it uses the options specified on the
 * ajax object.
 */
Drupal.ajax.prototype.eventResponse = function (element, event) {
  // Create a synonym for this to reduce code confusion.
  var ajax = this;

  // Do not perform another ajax command if one is already in progress.
  if (ajax.ajaxing) {
    return false;
  }

  try {
    if (ajax.form) {
      // If setClick is set, we must set this to ensure that the button's
      // value is passed.
      if (ajax.setClick) {
        // Mark the clicked button. 'form.clk' is a special variable for
        // ajaxSubmit that tells the system which element got clicked to
        // trigger the submit. Without it there would be no 'op' or
        // equivalent.
        element.form.clk = element;
      }

      ajax.form.ajaxSubmit(ajax.options);
    }
    else {
      ajax.beforeSerialize(ajax.element, ajax.options);
      $.ajax(ajax.options);
    }
  }
  catch (e) {
    // Unset the ajax.ajaxing flag here because it won't be unset during
    // the complete response.
    ajax.ajaxing = false;
    alert("An error occurred while attempting to process " + ajax.options.url + ": " + e.message);
  }

  // For radio/checkbox, allow the default event. On IE, this means letting
  // it actually check the box.
  if (typeof element.type != 'undefined' && (element.type == 'checkbox' || element.type == 'radio')) {
    return true;
  }
  else {
    return false;
  }

};

/**
 * Handler for the form serialization.
 *
 * Runs before the beforeSend() handler (see below), and unlike that one, runs
 * before field data is collected.
 */
Drupal.ajax.prototype.beforeSerialize = function (element, options) {
  // Allow detaching behaviors to update field values before collecting them.
  // This is only needed when field values are added to the POST data, so only
  // when there is a form such that this.form.ajaxSubmit() is used instead of
  // $.ajax(). When there is no form and $.ajax() is used, beforeSerialize()
  // isn't called, but don't rely on that: explicitly check this.form.
  if (this.form) {
    var settings = this.settings || Drupal.settings;
    Drupal.detachBehaviors(this.form, settings, 'serialize');
  }

  // Prevent duplicate HTML ids in the returned markup.
  // @see drupal_html_id()
  options.data['ajax_html_ids[]'] = [];
  $('[id]').each(function () {
    options.data['ajax_html_ids[]'].push(this.id);
  });

  // Allow Drupal to return new JavaScript and CSS files to load without
  // returning the ones already loaded.
  // @see ajax_base_page_theme()
  // @see drupal_get_css()
  // @see drupal_get_js()
  options.data['ajax_page_state[theme]'] = Drupal.settings.ajaxPageState.theme;
  options.data['ajax_page_state[theme_token]'] = Drupal.settings.ajaxPageState.theme_token;
  for (var key in Drupal.settings.ajaxPageState.css) {
    options.data['ajax_page_state[css][' + key + ']'] = 1;
  }
  for (var key in Drupal.settings.ajaxPageState.js) {
    options.data['ajax_page_state[js][' + key + ']'] = 1;
  }
};

/**
 * Modify form values prior to form submission.
 */
Drupal.ajax.prototype.beforeSubmit = function (form_values, element, options) {
  // This function is left empty to make it simple to override for modules
  // that wish to add functionality here.
}

/**
 * Prepare the Ajax request before it is sent.
 */
Drupal.ajax.prototype.beforeSend = function (xmlhttprequest, options) {
  // For forms without file inputs, the jQuery Form plugin serializes the form
  // values, and then calls jQuery's $.ajax() function, which invokes this
  // handler. In this circumstance, options.extraData is never used. For forms
  // with file inputs, the jQuery Form plugin uses the browser's normal form
  // submission mechanism, but captures the response in a hidden IFRAME. In this
  // circumstance, it calls this handler first, and then appends hidden fields
  // to the form to submit the values in options.extraData. There is no simple
  // way to know which submission mechanism will be used, so we add to extraData
  // regardless, and allow it to be ignored in the former case.
  if (this.form) {
    options.extraData = options.extraData || {};

    // Let the server know when the IFRAME submission mechanism is used. The
    // server can use this information to wrap the JSON response in a TEXTAREA,
    // as per http://jquery.malsup.com/form/#file-upload.
    options.extraData.ajax_iframe_upload = '1';

    // The triggering element is about to be disabled (see below), but if it
    // contains a value (e.g., a checkbox, textfield, select, etc.), ensure that
    // value is included in the submission. As per above, submissions that use
    // $.ajax() are already serialized prior to the element being disabled, so
    // this is only needed for IFRAME submissions.
    var v = $.fieldValue(this.element);
    if (v !== null) {
      options.extraData[this.element.name] = v;
    }
  }

  // Disable the element that received the change to prevent user interface
  // interaction while the Ajax request is in progress. ajax.ajaxing prevents
  // the element from triggering a new request, but does not prevent the user
  // from changing its value.
  $(this.element).addClass('progress-disabled').attr('disabled', true);

  // Insert progressbar or throbber.
  if (this.progress.type == 'bar') {
    var progressBar = new Drupal.progressBar('ajax-progress-' + this.element.id, eval(this.progress.update_callback), this.progress.method, eval(this.progress.error_callback));
    if (this.progress.message) {
      progressBar.setProgress(-1, this.progress.message);
    }
    if (this.progress.url) {
      progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500);
    }
    this.progress.element = $(progressBar.element).addClass('ajax-progress ajax-progress-bar');
    this.progress.object = progressBar;
    $(this.element).after(this.progress.element);
  }
  else if (this.progress.type == 'throbber') {
    this.progress.element = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber">&nbsp;</div></div>');
    if (this.progress.message) {
      $('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>');
    }
    $(this.element).after(this.progress.element);
  }
};

/**
 * Handler for the form redirection completion.
 */
Drupal.ajax.prototype.success = function (response, status) {
  // Remove the progress element.
  if (this.progress.element) {
    $(this.progress.element).remove();
  }
  if (this.progress.object) {
    this.progress.object.stopMonitoring();
  }
  $(this.element).removeClass('progress-disabled').removeAttr('disabled');

  Drupal.freezeHeight();

  for (var i in response) {
    if (response[i]['command'] && this.commands[response[i]['command']]) {
      this.commands[response[i]['command']](this, response[i], status);
    }
  }

  // Reattach behaviors, if they were detached in beforeSerialize(). The
  // attachBehaviors() called on the new content from processing the response
  // commands is not sufficient, because behaviors from the entire form need
  // to be reattached.
  if (this.form) {
    var settings = this.settings || Drupal.settings;
    Drupal.attachBehaviors(this.form, settings);
  }

  Drupal.unfreezeHeight();

  // Remove any response-specific settings so they don't get used on the next
  // call by mistake.
  this.settings = null;
};

/**
 * Build an effect object which tells us how to apply the effect when adding new HTML.
 */
Drupal.ajax.prototype.getEffect = function (response) {
  var type = response.effect || this.effect;
  var speed = response.speed || this.speed;

  var effect = {};
  if (type == 'none') {
    effect.showEffect = 'show';
    effect.hideEffect = 'hide';
    effect.showSpeed = '';
  }
  else if (type == 'fade') {
    effect.showEffect = 'fadeIn';
    effect.hideEffect = 'fadeOut';
    effect.showSpeed = speed;
  }
  else {
    effect.showEffect = type + 'Toggle';
    effect.hideEffect = type + 'Toggle';
    effect.showSpeed = speed;
  }

  return effect;
};

/**
 * Handler for the form redirection error.
 */
Drupal.ajax.prototype.error = function (response, uri) {
  alert(Drupal.ajaxError(response, uri));
  // Remove the progress element.
  if (this.progress.element) {
    $(this.progress.element).remove();
  }
  if (this.progress.object) {
    this.progress.object.stopMonitoring();
  }
  // Undo hide.
  $(this.wrapper).show();
  // Re-enable the element.
  $(this.element).removeClass('progress-disabled').removeAttr('disabled');
  // Reattach behaviors, if they were detached in beforeSerialize().
  if (this.form) {
    var settings = response.settings || this.settings || Drupal.settings;
    Drupal.attachBehaviors(this.form, settings);
  }
};

/**
 * Provide a series of commands that the server can request the client perform.
 */
Drupal.ajax.prototype.commands = {
  /**
   * Command to insert new content into the DOM.
   */
  insert: function (ajax, response, status) {
    // Get information from the response. If it is not there, default to
    // our presets.
    var wrapper = response.selector ? $(response.selector) : $(ajax.wrapper);
    var method = response.method || ajax.method;
    var effect = ajax.getEffect(response);

    // We don't know what response.data contains: it might be a string of text
    // without HTML, so don't rely on jQuery correctly iterpreting
    // $(response.data) as new HTML rather than a CSS selector. Also, if
    // response.data contains top-level text nodes, they get lost with either
    // $(response.data) or $('<div></div>').replaceWith(response.data).
    var new_content_wrapped = $('<div></div>').html(response.data);
    var new_content = new_content_wrapped.contents();

    // For legacy reasons, the effects processing code assumes that new_content
    // consists of a single top-level element. Also, it has not been
    // sufficiently tested whether attachBehaviors() can be successfully called
    // with a context object that includes top-level text nodes. However, to
    // give developers full control of the HTML appearing in the page, and to
    // enable Ajax content to be inserted in places where DIV elements are not
    // allowed (e.g., within TABLE, TR, and SPAN parents), we check if the new
    // content satisfies the requirement of a single top-level element, and
    // only use the container DIV created above when it doesn't. For more
    // information, please see http://drupal.org/node/736066.
    if (new_content.length != 1 || new_content.get(0).nodeType != 1) {
      new_content = new_content_wrapped;
    }

    // If removing content from the wrapper, detach behaviors first.
    switch (method) {
      case 'html':
      case 'replaceWith':
      case 'replaceAll':
      case 'empty':
      case 'remove':
        var settings = response.settings || ajax.settings || Drupal.settings;
        Drupal.detachBehaviors(wrapper, settings);
    }

    // Add the new content to the page.
    wrapper[method](new_content);

    // Immediately hide the new content if we're using any effects.
    if (effect.showEffect != 'show') {
      new_content.hide();
    }

    // Determine which effect to use and what content will receive the
    // effect, then show the new content.
    if ($('.ajax-new-content', new_content).length > 0) {
      $('.ajax-new-content', new_content).hide();
      new_content.show();
      $('.ajax-new-content', new_content)[effect.showEffect](effect.showSpeed);
    }
    else if (effect.showEffect != 'show') {
      new_content[effect.showEffect](effect.showSpeed);
    }

    // Attach all JavaScript behaviors to the new content, if it was successfully
    // added to the page, this if statement allows #ajax['wrapper'] to be
    // optional.
    if (new_content.parents('html').length > 0) {
      // Apply any settings from the returned JSON if available.
      var settings = response.settings || ajax.settings || Drupal.settings;
      Drupal.attachBehaviors(new_content, settings);
    }
  },

  /**
   * Command to remove a chunk from the page.
   */
  remove: function (ajax, response, status) {
    var settings = response.settings || ajax.settings || Drupal.settings;
    Drupal.detachBehaviors($(response.selector), settings);
    $(response.selector).remove();
  },

  /**
   * Command to mark a chunk changed.
   */
  changed: function (ajax, response, status) {
    if (!$(response.selector).hasClass('ajax-changed')) {
      $(response.selector).addClass('ajax-changed');
      if (response.asterisk) {
        $(response.selector).find(response.asterisk).append(' <span class="ajax-changed">*</span> ');
      }
    }
  },

  /**
   * Command to provide an alert.
   */
  alert: function (ajax, response, status) {
    alert(response.text, response.title);
  },

  /**
   * Command to provide the jQuery css() function.
   */
  css: function (ajax, response, status) {
    $(response.selector).css(response.argument);
  },

  /**
   * Command to set the settings that will be used for other commands in this response.
   */
  settings: function (ajax, response, status) {
    if (response.merge) {
      $.extend(true, Drupal.settings, response.settings);
    }
    else {
      ajax.settings = response.settings;
    }
  },

  /**
   * Command to attach data using jQuery's data API.
   */
  data: function (ajax, response, status) {
    $(response.selector).data(response.name, response.value);
  },

  /**
   * Command to apply a jQuery method.
   */
  invoke: function (ajax, response, status) {
    var $element = $(response.selector);
    $element[response.method].apply($element, response.arguments);
  },

  /**
   * Command to restripe a table.
   */
  restripe: function (ajax, response, status) {
    // :even and :odd are reversed because jQuery counts from 0 and
    // we count from 1, so we're out of sync.
    // Match immediate children of the parent element to allow nesting.
    $('> tbody > tr:visible, > tr:visible', $(response.selector))
      .removeClass('odd even')
      .filter(':even').addClass('odd').end()
      .filter(':odd').addClass('even');
  }
};

})(jQuery);
;
/**
 * @file
 *
 * Implement a modal form.
 *
 * @see modal.inc for documentation.
 *
 * This javascript relies on the CTools ajax responder.
 */

(function ($) {
  // Make sure our objects are defined.
  Drupal.CTools = Drupal.CTools || {};
  Drupal.CTools.Modal = Drupal.CTools.Modal || {};

  /**
   * Display the modal
   *
   * @todo -- document the settings.
   */
  Drupal.CTools.Modal.show = function(choice) {
    var opts = {};

    if (choice && typeof choice == 'string' && Drupal.settings[choice]) {
      // This notation guarantees we are actually copying it.
      $.extend(true, opts, Drupal.settings[choice]);
    }
    else if (choice) {
      $.extend(true, opts, choice);
    }

    var defaults = {
      modalTheme: 'CToolsModalDialog',
      throbberTheme: 'CToolsModalThrobber',
      animation: 'show',
      animationSpeed: 'fast',
      modalSize: {
        type: 'scale',
        width: .8,
        height: .8,
        addWidth: 0,
        addHeight: 0,
        // How much to remove from the inner content to make space for the
        // theming.
        contentRight: 25,
        contentBottom: 45
      },
      modalOptions: {
        opacity: .55,
        background: '#fff'
      }
    };

    var settings = {};
    $.extend(true, settings, defaults, Drupal.settings.CToolsModal, opts);

    if (Drupal.CTools.Modal.currentSettings && Drupal.CTools.Modal.currentSettings != settings) {
      Drupal.CTools.Modal.modal.remove();
      Drupal.CTools.Modal.modal = null;
    }

    Drupal.CTools.Modal.currentSettings = settings;

    var resize = function(e) {
      // When creating the modal, it actually exists only in a theoretical
      // place that is not in the DOM. But once the modal exists, it is in the
      // DOM so the context must be set appropriately.
      var context = e ? document : Drupal.CTools.Modal.modal;

      if (Drupal.CTools.Modal.currentSettings.modalSize.type == 'scale') {
        var width = $(window).width() * Drupal.CTools.Modal.currentSettings.modalSize.width;
        var height = $(window).height() * Drupal.CTools.Modal.currentSettings.modalSize.height;
      }
      else {
        var width = Drupal.CTools.Modal.currentSettings.modalSize.width;
        var height = Drupal.CTools.Modal.currentSettings.modalSize.height;
      }

      // Use the additionol pixels for creating the width and height.
      $('div.ctools-modal-content', context).css({
        'width': width + Drupal.CTools.Modal.currentSettings.modalSize.addWidth + 'px',
        'height': height + Drupal.CTools.Modal.currentSettings.modalSize.addHeight + 'px'
      });
      $('div.ctools-modal-content .modal-content', context).css({
        'width': (width - Drupal.CTools.Modal.currentSettings.modalSize.contentRight) + 'px',
        'height': (height - Drupal.CTools.Modal.currentSettings.modalSize.contentBottom) + 'px'
      });
    }

    if (!Drupal.CTools.Modal.modal) {
      Drupal.CTools.Modal.modal = $(Drupal.theme(settings.modalTheme));
      if (settings.modalSize.type == 'scale') {
        $(window).bind('resize', resize);
      }
    }

    resize();

    $('span.modal-title', Drupal.CTools.Modal.modal).html(Drupal.CTools.Modal.currentSettings.loadingText);
    Drupal.CTools.Modal.modalContent(Drupal.CTools.Modal.modal, settings.modalOptions, settings.animation, settings.animationSpeed);
    $('#modalContent .modal-content').html(Drupal.theme(settings.throbberTheme));
  };

  /**
   * Hide the modal
   */
  Drupal.CTools.Modal.dismiss = function() {
    if (Drupal.CTools.Modal.modal) {
      Drupal.CTools.Modal.unmodalContent(Drupal.CTools.Modal.modal);
    }
  };

  /**
   * Provide the HTML to create the modal dialog.
   */
  Drupal.theme.prototype.CToolsModalDialog = function () {
    var html = ''
    html += '  <div id="ctools-modal">'
    html += '    <div class="ctools-modal-content">' // panels-modal-content
    html += '      <div class="modal-header">';
    html += '        <a class="close" href="#">';
    html +=            Drupal.CTools.Modal.currentSettings.closeText + Drupal.CTools.Modal.currentSettings.closeImage;
    html += '        </a>';
    html += '        <span id="modal-title" class="modal-title">&nbsp;</span>';
    html += '      </div>';
    html += '      <div id="modal-content" class="modal-content">';
    html += '      </div>';
    html += '    </div>';
    html += '  </div>';

    return html;
  }

  /**
   * Provide the HTML to create the throbber.
   */
  Drupal.theme.prototype.CToolsModalThrobber = function () {
    var html = '';
    html += '  <div id="modal-throbber">';
    html += '    <div class="modal-throbber-wrapper">';
    html +=        Drupal.CTools.Modal.currentSettings.throbber;
    html += '    </div>';
    html += '  </div>';

    return html;
  };

  /**
   * Figure out what settings string to use to display a modal.
   */
  Drupal.CTools.Modal.getSettings = function (object) {
    var match = $(object).attr('class').match(/ctools-modal-(\S+)/);
    if (match) {
      return match[1];
    }
  }

  /**
   * Click function for modals that can be cached.
   */
  Drupal.CTools.Modal.clickAjaxCacheLink = function () {
    Drupal.CTools.Modal.show(Drupal.CTools.Modal.getSettings(this));
    return Drupal.CTools.AJAX.clickAJAXCacheLink.apply(this);
  };

  /**
   * Handler to prepare the modal for the response
   */
  Drupal.CTools.Modal.clickAjaxLink = function () {
    Drupal.CTools.Modal.show(Drupal.CTools.Modal.getSettings(this));
    return false;
  };

  /**
   * Submit responder to do an AJAX submit on all modal forms.
   */
  Drupal.CTools.Modal.submitAjaxForm = function(e) {
    var url = $(this).attr('action');
    var form = $(this);

    setTimeout(function() { Drupal.CTools.AJAX.ajaxSubmit(form, url); }, 1);
    return false;
  }

  /**
   * Bind links that will open modals to the appropriate function.
   */
  Drupal.behaviors.ZZCToolsModal = {
    attach: function(context) {
      // Bind links
      // Note that doing so in this order means that the two classes can be
      // used together safely.
      /*
       * @todo remimplement the warm caching feature
      $('a.ctools-use-modal-cache:not(.ctools-use-modal-processed)', context)
        .addClass('ctools-use-modal-processed')
        .click(Drupal.CTools.Modal.clickAjaxCacheLink)
        .each(function () {
          Drupal.CTools.AJAX.warmCache.apply(this);
        });
        */

      $('a.ctools-use-modal:not(.ctools-use-modal-processed)', context)
        .addClass('ctools-use-modal-processed')
        .click(Drupal.CTools.Modal.clickAjaxLink)
        .each(function () {
          // Create a drupal ajax object
          var element_settings = {};
          if ($(this).attr('href')) {
            element_settings.url = $(this).attr('href');
            element_settings.event = 'click';
            element_settings.progress = { type: 'throbber' };
          }
          var base = $(this).attr('href');
          Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);

          // Attach the display behavior to the ajax object
        }
      );

      // Bind buttons
      $('input.ctools-use-modal:not(.ctools-use-modal-processed), button.ctools-use-modal:not(.ctools-use-modal-processed)', context)
        .addClass('ctools-use-modal-processed')
        .click(Drupal.CTools.Modal.clickAjaxLink)
        .each(function() {
          var button = this;
          var element_settings = {};

          // AJAX submits specified in this manner automatically submit to the
          // normal form action.
          element_settings.url = Drupal.CTools.Modal.findURL(this);
          element_settings.event = 'click';

          var base = $(this).attr('id');
          Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);

          // Make sure changes to settings are reflected in the URL.
          $('.' + $(button).attr('id') + '-url').change(function() {
            Drupal.ajax[base].options.url = Drupal.CTools.Modal.findURL(button);
          });
        });

      // Bind our custom event to the form submit
      $('#modal-content form:not(.ctools-use-modal-processed)', context)
        .addClass('ctools-use-modal-processed')
        .each(function() {
          var element_settings = {};

          element_settings.url = $(this).attr('action');
          element_settings.event = 'submit';
          element_settings.progress = { 'type': 'throbber' }
          var base = $(this).attr('id');

          Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
          Drupal.ajax[base].form = $(this);

          $('input[type=submit], button', this).click(function() {
            Drupal.ajax[base].element = this;
            this.form.clk = this;
          });

        });
    }
  };

  // The following are implementations of AJAX responder commands.

  /**
   * AJAX responder command to place HTML within the modal.
   */
  Drupal.CTools.Modal.modal_display = function(ajax, response, status) {
    if ($('#modalContent').length == 0) {
      Drupal.CTools.Modal.show(Drupal.CTools.Modal.getSettings(ajax.element));
    }
    $('#modal-title').html(response.title);
    $('#modal-content').html(response.output);
    Drupal.attachBehaviors();
  }

  /**
   * AJAX responder command to dismiss the modal.
   */
  Drupal.CTools.Modal.modal_dismiss = function(command) {
    Drupal.CTools.Modal.dismiss();
    $('link.ctools-temporary-css').remove();
  }

  /**
   * Display loading
   */
  //Drupal.CTools.AJAX.commands.modal_loading = function(command) {
  Drupal.CTools.Modal.modal_loading = function(command) {
    Drupal.CTools.Modal.modal_display({
      output: Drupal.theme(Drupal.CTools.Modal.currentSettings.throbberTheme),
      title: Drupal.CTools.Modal.currentSettings.loadingText
    });
  }

  /**
   * Find a URL for an AJAX button.
   *
   * The URL for this gadget will be composed of the values of items by
   * taking the ID of this item and adding -url and looking for that
   * class. They need to be in the form in order since we will
   * concat them all together using '/'.
   */
  Drupal.CTools.Modal.findURL = function(item) {
    var url = '';
    var url_class = '.' + $(item).attr('id') + '-url';
    $(url_class).each(
      function() {
        if (url && $(this).val()) {
          url += '/';
        }
        url += $(this).val();
      });
    return url;
  };


  /**
   * modalContent
   * @param content string to display in the content box
   * @param css obj of css attributes
   * @param animation (fadeIn, slideDown, show)
   * @param speed (valid animation speeds slow, medium, fast or # in ms)
   */
  Drupal.CTools.Modal.modalContent = function(content, css, animation, speed) {
    // If our animation isn't set, make it just show/pop
    if (!animation) {
      animation = 'show';
    }
    else {
      // If our animation isn't "fadeIn" or "slideDown" then it always is show
      if (animation != 'fadeIn' && animation != 'slideDown') {
        animation = 'show';
      }
    }

    if (!speed) {
      speed = 'fast';
    }

    // Build our base attributes and allow them to be overriden
    css = jQuery.extend({
      position: 'absolute',
      left: '0px',
      margin: '0px',
      background: '#000',
      opacity: '.55'
    }, css);

    // Add opacity handling for IE.
    css.filter = 'alpha(opacity=' + (100 * css.opacity) + ')';
    content.hide();

    // if we already ahve a modalContent, remove it
    if ( $('#modalBackdrop')) $('#modalBackdrop').remove();
    if ( $('#modalContent')) $('#modalContent').remove();

    // position code lifted from http://www.quirksmode.org/viewport/compatibility.html
    if (self.pageYOffset) { // all except Explorer
    var wt = self.pageYOffset;
    } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict
      var wt = document.documentElement.scrollTop;
    } else if (document.body) { // all other Explorers
      var wt = document.body.scrollTop;
    }

    // Get our dimensions

    // Get the docHeight and (ugly hack) add 50 pixels to make sure we dont have a *visible* border below our div
    var docHeight = $(document).height() + 50;
    var docWidth = $(document).width();
    var winHeight = $(window).height();
    var winWidth = $(window).width();
    if( docHeight < winHeight ) docHeight = winHeight;

    // Create our divs
    $('body').append('<div id="modalBackdrop" style="z-index: 1000; display: none;"></div><div id="modalContent" style="z-index: 1001; position: absolute;">' + $(content).html() + '</div>');

    // Keyboard and focus event handler ensures focus stays on modal elements only
    modalEventHandler = function( event ) {
      target = null;
      if ( event ) { //Mozilla
        target = event.target;
      } else { //IE
        event = window.event;
        target = event.srcElement;
      }

      var parents = $(target).parents().get();
      for (var i in $(target).parents().get()) {
        var position = $(parents[i]).css('position');
        if (position == 'absolute' || position == 'fixed') {
          return true;
        }
      }
      if( $(target).filter('*:visible').parents('#modalContent').size()) {
        // allow the event only if target is a visible child node of #modalContent
        return true;
      }
      if ( $('#modalContent')) $('#modalContent').get(0).focus();
      return false;
    };
    $('body').bind( 'focus', modalEventHandler );
    $('body').bind( 'keypress', modalEventHandler );

    // Create our content div, get the dimensions, and hide it
    var modalContent = $('#modalContent').css('top','-1000px');
    var mdcTop = wt + ( winHeight / 2 ) - (  modalContent.outerHeight() / 2);
    var mdcLeft = ( winWidth / 2 ) - ( modalContent.outerWidth() / 2);
    $('#modalBackdrop').css(css).css('top', 0).css('height', docHeight + 'px').css('width', docWidth + 'px').show();
    modalContent.css({top: mdcTop + 'px', left: mdcLeft + 'px'}).hide()[animation](speed);

    // Bind a click for closing the modalContent
    modalContentClose = function(){close(); return false;};
    $('.close').bind('click', modalContentClose);

    // Close the open modal content and backdrop
    function close() {
      // Unbind the events
      $(window).unbind('resize',  modalContentResize);
      $('body').unbind( 'focus', modalEventHandler);
      $('body').unbind( 'keypress', modalEventHandler );
      $('.close').unbind('click', modalContentClose);
      $(document).trigger('CToolsDetachBehaviors', $('#modalContent'));

      // Set our animation parameters and use them
      if ( animation == 'fadeIn' ) animation = 'fadeOut';
      if ( animation == 'slideDown' ) animation = 'slideUp';
      if ( animation == 'show' ) animation = 'hide';

      // Close the content
      modalContent.hide()[animation](speed);

      // Remove the content
      $('#modalContent').remove();
      $('#modalBackdrop').remove();
    };

    // Move and resize the modalBackdrop and modalContent on resize of the window
     modalContentResize = function(){
      // Get our heights
      var docHeight = $(document).height();
      var docWidth = $(document).width();
      var winHeight = $(window).height();
      var winWidth = $(window).width();
      if( docHeight < winHeight ) docHeight = winHeight;

      // Get where we should move content to
      var modalContent = $('#modalContent');
      var mdcTop = ( winHeight / 2 ) - (  modalContent.outerHeight() / 2);
      var mdcLeft = ( winWidth / 2 ) - ( modalContent.outerWidth() / 2);

      // Apply the changes
      $('#modalBackdrop').css('height', docHeight + 'px').css('width', docWidth + 'px').show();
      modalContent.css('top', mdcTop + 'px').css('left', mdcLeft + 'px').show();
    };
    $(window).bind('resize', modalContentResize);

    $('#modalContent').focus();
  };

  /**
   * unmodalContent
   * @param content (The jQuery object to remove)
   * @param animation (fadeOut, slideUp, show)
   * @param speed (valid animation speeds slow, medium, fast or # in ms)
   */
  Drupal.CTools.Modal.unmodalContent = function(content, animation, speed)
  {
    // If our animation isn't set, make it just show/pop
    if (!animation) { var animation = 'show'; } else {
      // If our animation isn't "fade" then it always is show
      if (( animation != 'fadeOut' ) && ( animation != 'slideUp')) animation = 'show';
    }
    // Set a speed if we dont have one
    if ( !speed ) var speed = 'fast';

    // Unbind the events we bound
    $(window).unbind('resize', modalContentResize);
    $('body').unbind('focus', modalEventHandler);
    $('body').unbind('keypress', modalEventHandler);
    $('.close').unbind('click', modalContentClose);
    $(document).trigger('CToolsDetachBehaviors', $('#modalContent'));

    // jQuery magic loop through the instances and run the animations or removal.
    content.each(function(){
      if ( animation == 'fade' ) {
        $('#modalContent').fadeOut(speed,function(){$('#modalBackdrop').fadeOut(speed, function(){$(this).remove();});$(this).remove();});
      } else {
        if ( animation == 'slide' ) {
          $('#modalContent').slideUp(speed,function(){$('#modalBackdrop').slideUp(speed, function(){$(this).remove();});$(this).remove();});
        } else {
          $('#modalContent').remove();$('#modalBackdrop').remove();
        }
      }
    });
  };

$(function() {
  Drupal.ajax.prototype.commands.modal_display = Drupal.CTools.Modal.modal_display;
  Drupal.ajax.prototype.commands.modal_dismiss = Drupal.CTools.Modal.modal_dismiss;
});

})(jQuery);
;
/**
 * @file
 * Javascript for the custom module.
 *
 * @copyright (c) Copyright 2011 Palantir.net
 */

(function ($) {

$.extend(Drupal.settings, { "basePath": "/" });

Drupal.behaviors.custom = {
  attach: function (context) {
    var leaveMessage = Drupal.settings.custom.leaveMessage;

    $('.affiliate-link-link').click(function(event){
      var href = this.href

      jConfirm(leaveMessage, 'Confirm page redirection', function(r) {
        if (r) {
          window.location = href;
        }
      });

      return false;
    });


  }
};

/**
 * Custom theme for the Find Your State modal.
 */
Drupal.theme.prototype.FindYourStateModal = function () {
  var html = ''
  html += '  <div id="ctools-modal">'
  html += '    <div class="ctools-modal-content">' // panels-modal-content
  html += '      <div class="modal-header">';
  html += '        <a class="close" href="#">';
  html +=            Drupal.t('Close') + Drupal.CTools.Modal.currentSettings.closeImage;
  html += '        </a>';
  html += '        <span id="modal-title" class="modal-title"> </span>';
  html += '      </div>';
  html += '      <div id="modal-content" class="modal-content">';
  html += '      </div>';
  html += '    </div>';
  html += '  </div>';

  return html;
}

})(jQuery);
;
/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * TERMS OF USE - jQuery Easing
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2008 George McGinley Smith
 * All rights reserved.
 * 
 * Redistribution and use 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 the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * 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. 
 *
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend( jQuery.easing,
{
	def: 'easeOutQuad',
	swing: function (x, t, b, c, d) {
		//alert(jQuery.easing.default);
		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
	},
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158; 
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});

/*
 *
 * TERMS OF USE - EASING EQUATIONS
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2001 Robert Penner
 * All rights reserved.
 * 
 * Redistribution and use 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 the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * 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. 
 *
 */;
﻿/**
 * jQuery.timers - Timer abstractions for jQuery
 * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
 * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
 * Date: 2009/10/16
 *
 * @author Blair Mitchelmore
 * @version 1.2
 *
 **/

jQuery.fn.extend({
	everyTime: function(interval, label, fn, times) {
		return this.each(function() {
			jQuery.timer.add(this, interval, label, fn, times);
		});
	},
	oneTime: function(interval, label, fn) {
		return this.each(function() {
			jQuery.timer.add(this, interval, label, fn, 1);
		});
	},
	stopTime: function(label, fn) {
		return this.each(function() {
			jQuery.timer.remove(this, label, fn);
		});
	}
});

jQuery.extend({
	timer: {
		global: [],
		guid: 1,
		dataKey: "jQuery.timer",
		regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
		powers: {
			// Yeah this is major overkill...
			'ms': 1,
			'cs': 10,
			'ds': 100,
			's': 1000,
			'das': 10000,
			'hs': 100000,
			'ks': 1000000
		},
		timeParse: function(value) {
			if (value == undefined || value == null)
				return null;
			var result = this.regex.exec(jQuery.trim(value.toString()));
			if (result[2]) {
				var num = parseFloat(result[1]);
				var mult = this.powers[result[2]] || 1;
				return num * mult;
			} else {
				return value;
			}
		},
		add: function(element, interval, label, fn, times) {
			var counter = 0;
			
			if (jQuery.isFunction(label)) {
				if (!times) 
					times = fn;
				fn = label;
				label = interval;
			}
			
			interval = jQuery.timer.timeParse(interval);

			if (typeof interval != 'number' || isNaN(interval) || interval < 0)
				return;

			if (typeof times != 'number' || isNaN(times) || times < 0) 
				times = 0;
			
			times = times || 0;
			
			var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});
			
			if (!timers[label])
				timers[label] = {};
			
			fn.timerID = fn.timerID || this.guid++;
			
			var handler = function() {
				if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
					jQuery.timer.remove(element, label, fn);
			};
			
			handler.timerID = fn.timerID;
			
			if (!timers[label][fn.timerID])
				timers[label][fn.timerID] = window.setInterval(handler,interval);
			
			this.global.push( element );
			
		},
		remove: function(element, label, fn) {
			var timers = jQuery.data(element, this.dataKey), ret;
			
			if ( timers ) {
				
				if (!label) {
					for ( label in timers )
						this.remove(element, label, fn);
				} else if ( timers[label] ) {
					if ( fn ) {
						if ( fn.timerID ) {
							window.clearInterval(timers[label][fn.timerID]);
							delete timers[label][fn.timerID];
						}
					} else {
						for ( var fn in timers[label] ) {
							window.clearInterval(timers[label][fn]);
							delete timers[label][fn];
						}
					}
					
					for ( ret in timers[label] ) break;
					if ( !ret ) {
						ret = null;
						delete timers[label];
					}
				}
				
				for ( ret in timers ) break;
				if ( !ret ) 
					jQuery.removeData(element, this.dataKey);
			}
		}
	}
});

jQuery(window).bind("unload", function() {
	jQuery.each(jQuery.timer.global, function(index, item) {
		jQuery.timer.remove(item);
	});
});;
/*
**
**	GalleryView - jQuery Content Gallery Plugin
**	Author: 		Jack Anderson
**	Version:		3.0b3 (March 15, 2011)
**
**	Please use this development script if you intend to make changes to the
**	plugin code.  For production sites, it is recommended you use jquery.galleryview-3.0.min.js.
**
**  See README.txt for instructions on how to markup your HTML
**
**	See CHANGELOG.txt for a review of changes and LICENSE.txt for the applicable
**	licensing information.
**
*/

//Global variable to check if window is already loaded
//Used for calling GalleryView after page has loaded
var window_loaded = false;
jQuery(window).load(function(){
	window_loaded = true;
});
(function($){
	$.fn.galleryView = function(options) {
		var opts = $.extend($.fn.galleryView.defaults,options);

		var id;
		var iterator = 0;			// INT - Currently visible panel/frame
		var item_count = 0;			// INT - Total number of panels/frames
		var slide_method;			// STRING - indicator to slide entire filmstrip or just the pointer ('strip','pointer')
		var paused = false;			// BOOLEAN - flag to indicate whether automated transitions are active
		var pointer_speed = 0;		// INT - Speed (in milliseconds) of pointer animation
		var animate_panels = true;	// BOOLEAN - flag to indicate whether panels will animate during transitions
		var current = 1;			// INT - index of current panel/frame
		var gallery_images;			// OBJECT - container for images within UL passed to plugin
		var image_count = 0;		// INT - number of images within gallery
		var loaded_images = 0;		// INT - number of gallery images that have been loaded in the browser

	// Element dimensions
		var gallery_width;
		var gallery_height;
		var pointer_height;
		var pointer_width;
		var strip_width;
		var strip_height;
		var wrapper_width;
		var wrapper_height;
		var f_frame_width;
		var f_frame_height;
		var filmstrip_orientation;


	// Arrays used to scale frames and panels
		var frame_img_scale = {};
		var panel_img_scale = {};
		var img_h = {};
		var img_w = {};

	// Flag indicating whether to scale panel images
		var scale_panel_images = true;

		var panel_nav_displayed = false;

	// Define jQuery objects for reuse
		var j_gallery;
		var j_filmstrip;
		var j_frames;
		var j_frame_img_wrappers;
		var j_panels;
		var j_pointer;
		var j_panel_wrapper;


/*
**	Plugin Functions
*/

	/*
	**	showItem(int,boolean,function)
	**		Transition from current frame to frame i (1-based index)
	**		skip_animation flag let's us override transition speed to show an item instantly
	**		(useful when loading gallery for the first time)
	**		If provided, run callback function after transition completes
	*/
		function showItem(i,speed,callback) {
			// A scrolling filmstrip will contain three copies of each frame, we want to know the relative position of the target frame
			var mod_i = i%item_count;
			var distance;
			var diststr;

			// Disable next/prev buttons until transition is complete
			// This prevents overlapping of animations
			$('.gv-nav-next, .gv-panel-nav-next, .gv-nav-prev, .gv-panel-nav-prev',j_gallery).unbind('click');
			j_frames.unbind('click');

			// Use timer to rebind navigation buttons when transition ends
			$(document).oneTime(speed,'bindNavButtons',function(){
				$('.gv-nav-next, .gv-panel-nav-next',j_gallery).click(showNextItem);
				$('.gv-nav-prev, .gv-panel-nav-prev',j_gallery).click(showPrevItem);
				enableFrameClicking();
			});

			if(opts.show_filmstrip) {

				// Fade out all frames
				j_frames.removeClass('current').find('img').stop().animate({opacity:opts.frame_opacity},speed);

				// Fade in target frame
				j_frames.eq(i).addClass('current').find('img').stop().animate({opacity:1},speed);
			}

			//If necessary, transition between panels
			if(opts.show_panels) {
				if(animate_panels) {
					if(opts.panel_animation=='slide') {

						// Move target frame just to the right of the current frame
						j_panels.eq(mod_i).css({
							left: getInt($('.gv-panel.current').eq(0).css('left'))+opts.panel_width+'px',
							zIndex: 50
						}).show().animate({
							left: '-='+opts.panel_width+'px'
						},speed,opts.easing,function(){
							$(this).addClass('current');
						});

						// Slide current frame and target frame to the left
						$('.gv-panel.current').css({zIndex:49}).animate({
							left: '-='+opts.panel_width+'px'
						},speed,opts.easing,function(){
							$(this).removeClass('current').hide();
						});
					} else if(opts.panel_animation=='zoomOut') {

						// After zoom is complete, add 'current' class to now visible panel and move it to top of stack via z-index
						$(document).oneTime(speed,'setCurrentFrame',function(){
							j_panels.eq(mod_i).addClass('current').css('zIndex',50);
						});

						// Show target panel and place below current frame via z-index
						j_panels.eq(mod_i).show().css('zIndex',49);

						// Shrink panel container to center while moving image in opposite direction
						// End result is an image that remains static while borders of container shrink
						$('.gv-panel.current img').animate({
							top: '-='+opts.panel_height/2+'px',
							left:'-='+opts.panel_width/2+'px'
						},speed,'swing',function(){

							// After zoom is complete, immediately animate it back to its original position for next time
							$(this).animate({
								top: '+='+opts.panel_height/2+'px',
								left: '+='+opts.panel_width/2+'px'
							},0);
						});

						$('.gv-panel.current').animate({
							top:'+='+opts.panel_height/2+'px',
							left:'+='+opts.panel_width/2+'px',
							height:0,
							width:0
						},speed,'swing',function(){
							$(this).removeClass('current').hide().css({
								top:getPos(j_panels[mod_i]).top+'px',
								left:getPos(j_panels[mod_i]).left+'px',
								height:opts.panel_height+'px',
								width:opts.panel_width+'px'
							});
						});
					} else if(opts.panel_animation == 'crossfade') {

						// Default behavior is to fade panel into view
						j_panels.removeClass('current').fadeOut(speed,function(){$(this).css('filter','');}).eq(mod_i).addClass('current').fadeIn(speed,function(){$(this).css('filter','');});
					} else {

						// Fade out panels, and then fade in target panel
						// Use timer due to inconsistency in fadeIn/fadeOut callback reliability
						j_panels.removeClass('current').stop().fadeOut(speed/2);
						$(document).oneTime(speed/2,'fadeInPanel',function(){
							j_panels.eq(mod_i).addClass('current').stop().fadeIn(speed/2);
						});
					}
				} else {

					// If no animation style is chosen, simply show the new panel instantly
					$(document).oneTime(speed,'switch_panels',function(){j_panels.hide().eq(mod_i).show();});
				}
			}

			// If gallery has a filmstrip, handle animation of frames
			if(opts.show_filmstrip) {

				// Slide either pointer or filmstrip, depending on transition method
				if(opts.filmstrip_style == 'scroll' && slide_method=='strip') {

					// Stop filmstrip if it's currently in motion
					j_filmstrip.stop();

					if(filmstrip_orientation=='horizontal') {

						// Determine distance between pointer (eventual destination) and target frame
						distance = getPos(j_frames[i]).left - (getPos(j_pointer[0]).left+(pointer_width/2)-(f_frame_width/2));
						diststr = (distance>=0?'-=':'+=')+Math.abs(distance)+'px';

						// Animate filmstrip and slide target frame under pointer
						j_filmstrip.animate({left:diststr},speed,opts.easing,function(){
							var old_i = i;

							// After transition is complete, shift filmstrip so that a sufficient number of frames
							// remain on either side of the visible filmstrip
							if(i>item_count) {
								i = mod_i;
								iterator = i;
								j_filmstrip.css('left','-'+((f_frame_width+opts.frame_gap)*i)+'px');
							} else if (i<=(item_count-strip_size)) {
								i = (mod_i)+item_count;
								iterator = i;
								j_filmstrip.css('left','-'+((f_frame_width+opts.frame_gap)*i)+'px');
							}

							// If the target frame has changed due to filmstrip shifting,
							// make sure new target frame has 'current' class and correct size/opacity settings
							if(old_i != i) {
								j_frames.eq(old_i).removeClass('current').find('img').css({opacity:opts.frame_opacity});
								j_frames.eq(i).addClass('current').find('img').css({opacity:1});
							}
						});
					} else {

						//Determine distance between pointer (eventual destination) and target frame
						distance = getPos(j_frames[i]).top-getPos($('.gv-strip-wrapper',j_gallery)[0]).top;
						diststr = (distance>=0?'-=':'+=')+Math.abs(distance)+'px';

						// Animate filmstrip and slide target frame under pointer
						j_filmstrip.animate({
							'top':diststr
						},speed,opts.easing,function(){

							// After transition is complete, shift filmstrip so that a sufficient number of frames
							// remain on either side of the visible filmstrip
							var old_i = i;
							if(i>item_count) {
								i = mod_i;
								iterator = i;
								j_filmstrip.css('top','-'+((f_frame_height+opts.frame_gap)*i)+'px');
							} else if (i<=(item_count-strip_size)) {
								i = (mod_i)+item_count;
								iterator = i;
								j_filmstrip.css('top','-'+((f_frame_height+opts.frame_gap)*i)+'px');
							}

							//If the target frame has changed due to filmstrip shifting,
							//Make sure new target frame has 'current' class and correct size/opacity settings
							if(old_i != i) {
								j_frames.eq(old_i).removeClass('current').find('img').css({opacity:opts.frame_opacity});
								j_frames.eq(i).addClass('current').find('img').css({opacity:1});
							}

							// If panels are not set to fade in/out, simply hide all panels and show the target panel
							if(!animate_panels) {
								j_panels.hide().eq(mod_i).show();
							}
						});
					}
				} else if(slide_method=='pointer') {

					// Stop pointer if it's currently in motion
					j_pointer.stop();

					// Get screen position of target frame
					var pos = getPos(j_frames[i]);

					if(filmstrip_orientation=='horizontal') {

						// Slide the pointer over the target frame
						j_pointer.animate({
							left:pos.left+(f_frame_width/2)-(pointer_width/2)+'px'
						},pointer_speed,opts.easing,function(){
							if(!animate_panels) {j_panels.hide().eq(mod_i).show();}
						});
					} else {

						// Slide the pointer over the target frame
						j_pointer.animate({
							top:pos.top+(f_frame_height/2)-(pointer_height)+'px'
						},pointer_speed,opts.easing,function(){
							if(!animate_panels) {j_panels.hide().eq(mod_i).show();}
						});
					}
				}
			}
			if(callback) {$(document).oneTime(speed,'showItemCallback',callback);}
			current = i;
		};

	/*
	**	extraWidth(jQuery element)
	**		Return the combined width of the border and padding to the elements left and right.
	**		If the border is non-numerical, assume zero (not ideal, will fix later)
	**		RETURNS - int
	*/
		function extraWidth(el) {
			if(!el) { return 0; }
			if(el.length==0) { return 0; }
			el = el.eq(0);
			var ew = 0;
			ew += getInt(el.css('paddingLeft'));
			ew += getInt(el.css('paddingRight'));
			ew += getInt(el.css('borderLeftWidth'));
			ew += getInt(el.css('borderRightWidth'));
			return ew;
		};

	/*
	**	extraHeight(jQuery element)
	**		Return the combined height of the border and padding above and below the element
	**		If the border is non-numerical, assume zero (not ideal, will fix later)
	**		RETURN - int
	*/
		function extraHeight(el) {
			if(!el) { return 0; }
			if(el.length==0) { return 0; }
			el = el.eq(0);
			var eh = 0;
			eh += getInt(el.css('paddingTop'));
			eh += getInt(el.css('paddingBottom'));
			eh += getInt(el.css('borderTopWidth'));
			eh += getInt(el.css('borderBottomWidth'));
			return eh;
		};

	/*
	**	showNextItem()
	**		Transition from current frame to next frame
	*/
		function showNextItem() {

			// Cancel any transition timers until we have completed this function
			$(document).stopTime("transition");
			if(++iterator==j_frames.length) {iterator=0;}

			// We've already written the code to transition to an arbitrary panel/frame, so use it
			showItem(iterator,opts.transition_speed);

			// If automated transitions haven't been cancelled by an option or paused on hover, re-enable them
			if(!paused && opts.transition_interval > 0) {
				$(document).everyTime(opts.transition_interval,"transition",function(){showNextItem();});
			}
		};

	/*
	**	showPrevItem()
	**		Transition from current frame to previous frame
	*/
		function showPrevItem() {

			// Cancel any transition timers until we have completed this function
			$(document).stopTime("transition");
			if(--iterator<0) {iterator = item_count-1;}

			// We've already written the code to transition to an arbitrary panel/frame, so use it
			showItem(iterator,opts.transition_speed);

			// If automated transitions haven't been cancelled by an option or paused on hover, re-enable them
			if(!paused && opts.transition_interval > 0) {
				$(document).everyTime(opts.transition_interval,"transition",function(){showNextItem();});
			}
		};

	/*
	**	getPos(jQuery element)
	**		Calculate position of an element relative to top/left corner of gallery
	**		If the gallery bounding box itself is passed to the function, calculate position of gallery relative to top/left corner of browser window
	** 		RETURNS - JSON {left: int, top: int}
	*/
		function getPos(el) {
			if(!el) return {top:0,left:0};
			var left = 0, top = 0;
			var el_id = el.id;
			if(el.offsetParent) {
				do {
					left += el.offsetLeft;
					top += el.offsetTop;
				} while(el = el.offsetParent);
			}

			//If we want the position of the gallery itself, return it
			if(el_id == id) {return {'left':left,'top':top};}

			//Otherwise, get position of element relative to gallery
			else {
				var gPos = getPos(j_gallery[0]);
				var gLeft = gPos.left;
				var gTop = gPos.top;

				return {'left':left-gLeft,'top':top-gTop};
			}
		};

	/*
	**	enableFrameClicking()
	**		Add an onclick event handler to each frame
	**		Exception: if a frame has an anchor tag, do not add an onlick handler
	*/
		function enableFrameClicking() {
			j_frames.each(function(i){
				if($('a',this).length==0) {
					$(this).click(function(){

						// Prevent transitioning to the current frame (unnecessary)
						if(iterator!=i) {
							$(document).stopTime("transition");
							showItem(i,opts.transition_speed);
							iterator = i;
							if(!paused && opts.transition_interval > 0) {
								$(document).everyTime(opts.transition_interval,"transition",function(){showNextItem();});
							}
						}
					});
				}
			});
		};

	/*
	**	buildPanels()
	**		Construct gallery panels: <div class="gv-panel"> elements
	**		NOTE - These DIVs are generated automatically from the content of the UL passed to the plugin
	*/
		function buildPanels() {

			// If panel overlay content exists, add the necessary overlay background DIV
			// The overlay content and background are separate elements so the background's opacity isn't inherited by the content
			j_panels.each(function(i){
		   		if($('.gv-panel-overlay',this).length>0) {
					$(this).append('<div class="gv-overlay-background"></div>');
				}
		   	});

			// If there is no filmstrip in this gallery, add navigation buttons to the panel itself
			if(opts.show_panel_nav) {
				$('<div></div>').addClass('gv-panel-nav-next').appendTo(j_gallery).css({
					position:'absolute',
					zIndex:'1100',
					top:((opts.filmstrip_position=='top'?opts.frame_gap+wrapper_height:0)+(opts.panel_height-22)/2)+'px',
					right:((opts.filmstrip_position=='right'?opts.frame_gap+wrapper_width:0)+10)+'px',
					display:'none'
				}).click(showNextItem);
				$('<div></div>').addClass('gv-panel-nav-prev').appendTo(j_gallery).css({
					position:'absolute',
					zIndex:'1100',
					top:((opts.filmstrip_position=='top'?opts.frame_gap+wrapper_height:0)+(opts.panel_height-22)/2)+'px',
					left:((opts.filmstrip_position=='left'?opts.frame_gap+wrapper_width:0)+10)+'px',
					display:'none'
				}).click(showPrevItem);
			}

			//Set size and position of panel container
			j_panel_wrapper.css({
				width:opts.panel_width+'px',
				height:opts.panel_height+'px',
				position:'absolute',
				overflow:'hidden'
			});

			if(opts.show_filmstrip) {
				switch(opts.filmstrip_position) {
					case 'top': j_panel_wrapper.css({top:wrapper_height+opts.frame_gap+'px'}); break;
					case 'left': j_panel_wrapper.css({left:wrapper_width+opts.frame_gap+'px'}); break;
					default: break;
				}
			}

			// Set the height and width of each panel, and position it appropriately within the gallery
			j_panels.each(function(i){
				$(this).css({
					width:(opts.panel_width-extraWidth(j_panels))+'px',
					height:(opts.panel_height-extraHeight(j_panels))+'px',
					position:'absolute',
					top:0,
					left:0,
					display:'none'
				});
			});

			// Position each panel overlay within panel
			$('.gv-panel-overlay',j_panels).css({
				position:'absolute',
				zIndex:'999',
				width:(opts.panel_width-extraWidth($('.gv-panel-overlay',j_panels)))+'px',
				left:0
			});
			$('.gv-overlay-background',j_panels).css({
				position:'absolute',
				zIndex:'998',
				width:opts.panel_width+'px',
				left:0,
				opacity:opts.overlay_opacity
			});
			if(opts.overlay_position=='top') {
				$('.gv-panel-overlay',j_panels).css('top',0);
				$('.gv-overlay-background',j_panels).css('top',0);
			} else {
				$('.gv-panel-overlay',j_panels).css('bottom',0);
				$('.gv-overlay-background',j_panels).css('bottom',0);
			}

			$('.gv-panel iframe',j_panels).css({
				width:opts.panel_width+'px',
				height:opts.panel_height+'px',
				border:0
			});

			// If panel images have to be scaled to fit within frame, do so and position them accordingly
			if(scale_panel_images) {
				$('img',j_panels).each(function(i){
					$(this).css({
						height:panel_img_scale[i%item_count]*img_h[i%item_count],
						width:panel_img_scale[i%item_count]*img_w[i%item_count],
						position:'relative',
						top:(opts.panel_height-(panel_img_scale[i%item_count]*img_h[i%item_count]))/2+'px',
						left:(opts.panel_width-(panel_img_scale[i%item_count]*img_w[i%item_count]))/2+'px'
					});
				});
			}
		};

	/*
	**	buildFilmstrip()
	**		Construct filmstrip from <ul class="gv-filmstrip"> element
	**		NOTE - 'filmstrip' class is automatically added to UL passed to plugin
	*/
		function buildFilmstrip() {

			// Add wrapper to filmstrip to hide extra frames
			j_filmstrip.wrap('<div class="gv-strip-wrapper"></div>');
			if(opts.filmstrip_style == 'scroll' && slide_method=='strip') {
				j_frames.clone().appendTo(j_filmstrip);
				j_frames.clone().appendTo(j_filmstrip);
				j_frames = $('li',j_filmstrip);
			}

			// If captions are enabled, add caption DIV to each frame and fill with the image titles
			if(opts.show_captions) {
				j_frames.append('<div class="gv-caption"></div>').each(function(i){
					$(this).find('.gv-caption').html($(this).find('img').attr('title'));
				});
			}

			// Position the filmstrip within the gallery
			j_filmstrip.css({
				listStyle:'none',
				margin:0,
				padding:0,
				width:strip_width+'px',
				position:'absolute',
				zIndex:'900',
				top:(filmstrip_orientation=='vertical' && opts.filmstrip_style == 'scroll' && slide_method=='strip'?-((f_frame_height+opts.frame_gap)*iterator):0)+'px',
				left:(filmstrip_orientation=='horizontal' && opts.filmstrip_style == 'scroll' && slide_method=='strip'?-((f_frame_width+opts.frame_gap)*iterator):0)+'px',
				height:strip_height+'px'
			});

			j_frames.css({
				float:'left',
				position:'relative',
				height:f_frame_height+(opts.show_captions?f_caption_height:0)+'px',
				width:f_frame_width+'px',
				zIndex:'901',
				padding:0,
				cursor:'pointer',
				marginBottom:opts.frame_gap+'px',
				marginRight:opts.frame_gap+'px'
			});

			// Apply styling to individual image wrappers. These will eventually hide overflow in the case of cropped filmstrip images
			$('.gv-img-wrap',j_frames).each(function(i){
				$(this).css({
					height:Math.min(opts.frame_height,img_h[i%item_count]*frame_img_scale[i%item_count])+'px',
					width:Math.min(opts.frame_width,img_w[i%item_count]*frame_img_scale[i%item_count])+'px',
					position:'relative',
					top:(opts.show_captions && opts.filmstrip_position=='top'?f_caption_height:0)+Math.max(0,(opts.frame_height-(frame_img_scale[i%item_count]*img_h[i%item_count]))/2)+'px',
					left:Math.max(0,(opts.frame_width-(frame_img_scale[i%item_count]*img_w[i%item_count]))/2)+'px',
					overflow:'hidden'
				});
			});

			// Scale each filmstrip image if necessary and position it within the image wrapper
			$('img',j_frames).each(function(i){
				$(this).css({
					opacity:opts.frame_opacity,
					height:img_h[i%item_count]*frame_img_scale[i%item_count]+'px',
					width:img_w[i%item_count]*frame_img_scale[i%item_count]+'px',
					position:'relative',
					top:Math.min(0,(opts.frame_height-(frame_img_scale[i%item_count]*img_h[i%item_count]))/2)+'px',
					left:Math.min(0,(opts.frame_width-(frame_img_scale[i%item_count]*img_w[i%item_count]))/2)+'px'
				}).mouseover(function(){
					$(this).stop().animate({opacity:1},300);
				}).mouseout(function(){
					//Don't fade out current frame on mouseout
					if(!$(this).parent().parent().hasClass('current')){$(this).stop().animate({opacity:opts.frame_opacity},300);}
				});
			});

			// Set overflow of filmstrip wrapper to hidden so as to hide frames that don't fit within the gallery
			$('.gv-strip-wrapper',j_gallery).css({
				position:'absolute',
				overflow:'hidden'
			});

			// Position filmstrip within gallery based on user options
			if(filmstrip_orientation=='horizontal') {
				$('.gv-strip-wrapper',j_gallery).css({
					top:opts.show_panels ? opts.filmstrip_position=='top'?0:opts.panel_height+opts.frame_gap+'px' : 0,
					left:((gallery_width-wrapper_width)/2)+'px',
					width:wrapper_width+'px',
					height:wrapper_height+'px'
				});
			} else {
				$('.gv-strip-wrapper',j_gallery).css({
					left:opts.show_panels ? opts.filmstrip_position=='left'?0:opts.panel_width+opts.frame_gap+'px' : 0,
					top:0,
					width:wrapper_width+'px',
					height:wrapper_height+'px'
				});
			}

			// Style frame captions
			$('.gv-caption',j_gallery).css({
				position:'absolute',
				top:(opts.filmstrip_position=='bottom'?f_frame_height:0)+'px',
				left:0,
				margin:0,
				width:f_caption_width+'px',
				overflow:'hidden'
			});

			// Create pointer for current frame
			var pointer = $('<div></div>');
			pointer.addClass('gv-pointer').appendTo(j_gallery).css({
				 position:'absolute',
				 zIndex:'1000',
				 width:0,
				 fontSize:0,
				 lineHeight:0,
				 borderTopWidth:pointer_height+'px',
				 borderRightWidth:(pointer_width/2)+'px',
				 borderBottomWidth:pointer_height+'px',
				 borderLeftWidth:(pointer_width/2)+'px',
				 borderStyle:'solid'
			});

			// For IE6, use predefined color string in place of transparent (IE6 bug fix, see stylesheet)
			var transColor = $.browser.msie && $.browser.version.substr(0,1) == '6' ? 'pink' : 'transparent';

			// If there are no panels, make pointer transparent (nothing to point to)
			// This is not the optimal solution, but we need the pointer to exist as a reference for transition animations
			if(!opts.show_panels) { pointer.css('borderColor',transColor); }
			switch(opts.filmstrip_position) {
				case 'top': pointer.css({
								top:wrapper_height+'px',
								left:((gallery_width-wrapper_width)/2)+(slide_method=='strip'?0:((f_frame_width+opts.frame_gap)*iterator))+((f_frame_width/2)-(pointer_width/2))+'px',
								borderBottomColor:transColor,
								borderRightColor:transColor,
								borderLeftColor:transColor
							}); break;
				case 'bottom': pointer.css({
									bottom:wrapper_height+'px',
									left:((gallery_width-wrapper_width)/2)+(slide_method=='strip'?0:((f_frame_width+opts.frame_gap)*iterator))+((f_frame_width/2)-(pointer_width/2))+'px',
									borderTopColor:transColor,
									borderRightColor:transColor,
									borderLeftColor:transColor
								}); break;
				case 'left': pointer.css({
								left:wrapper_width+'px',
								top:(f_frame_height/2)-(pointer_height)+(slide_method=='strip'?0:((f_frame_height+opts.frame_gap)*iterator))+'px',
								borderBottomColor:transColor,
								borderRightColor:transColor,
								borderTopColor:transColor
							}); break;
				case 'right': pointer.css({
								right:wrapper_width+'px',
								top:(f_frame_height/2)-(pointer_height)+(slide_method=='strip'?0:((f_frame_height+opts.frame_gap)*iterator))+'px',
								borderBottomColor:transColor,
								borderLeftColor:transColor,
								borderTopColor:transColor
							}); break;
			}

			j_pointer = $('.gv-pointer',j_gallery);

			// Add navigation buttons
			if(opts.show_filmstrip_nav) {
				var navNext = $('<div></div>');
				navNext.addClass('gv-nav-next').appendTo(j_gallery).css({
					position:'absolute'
				}).click(showNextItem);

				var navPrev = $('<div></div>');
				navPrev.addClass('gv-nav-prev').appendTo(j_gallery).css({
					position:'absolute'
				}).click(showPrevItem);

				if(filmstrip_orientation=='horizontal') {
					navNext.css({
						top:(opts.show_panels ? (opts.filmstrip_position=='top'?0:opts.panel_height+opts.frame_gap) : 0)+((strip_height-22)/2)+'px',
						right:((gallery_width)/2)-(wrapper_width/2)-opts.frame_gap-22+'px'
					});
					navPrev.css({
						top:(opts.show_panels ? (opts.filmstrip_position=='top'?0:opts.panel_height+opts.frame_gap) : 0)+((strip_height-22)/2)+'px',
						left:((gallery_width)/2)-(wrapper_width/2)-opts.frame_gap-22+'px'
					 });
				} else {
					navNext.css({
						left:(opts.show_panels ? (opts.filmstrip_position=='left'?0:opts.panel_width+opts.frame_gap) : 0)+((strip_width-22)/2)+13+'px',
						top:wrapper_height+opts.frame_gap+'px'
					});
					navPrev.css({
						left:(opts.show_panels ? (opts.filmstrip_position=='left'?0:opts.panel_width+opts.frame_gap) : 0)+((strip_width-22)/2)-13+'px',
						top:wrapper_height+opts.frame_gap+'px'
					});
				}
			}
		};

	/*
	**	mouseIsOverGallery(int,int)
	**		Check to see if mouse coordinates lie within borders of gallery
	**		This is a more reliable method than using the mouseover event
	**		RETURN - boolean
	*/
		function mouseIsOverGallery(x,y) {
			var pos = getPos(j_gallery[0]);
			var top = pos.top;
			var left = pos.left;
			return x > left && x < left+j_gallery.outerWidth() && y > top && y < top+j_gallery.outerHeight();
		};

	/*
	**	mouseIsOverPanel(int,int)
	**		Check to see if mouse coordinates lie within borders of panel
	**		This is a more reliable method than using the mouseover event
	**		RETURN - boolean
	*/
		function mouseIsOverPanel(x,y) {

			// Get position of panel wrapper in relation to gallery
			var pos = getPos($('#'+id+' .gv-panel-wrap')[0]);
			var gPos = getPos(j_gallery[0]);

			// Add wrap position to gallery position
			var top = pos.top+gPos.top;
			var left = pos.left+gPos.left;

			return x > left && x < left+j_panels.outerWidth() && y > top && y < top+j_panels.outerHeight();
		};

	/*
	**	getInt(string)
	**		Parse a string to obtain the integer value contained
	**		If the string contains no number, return zero
	**		RETURN - int
	*/
		function getInt(i) {
			i = parseInt(i,10);
			if(isNaN(i)) { i = 0; }
			return i;
		};

	/*
	**	buildGallery()
	**		Construct HTML and CSS for the gallery, based on user options
	*/
		function buildGallery() {

			// Get gallery images
			var gallery_images = opts.show_filmstrip?$('img',j_frames):$('img',j_panels);

			// For each image in the gallery, add its original dimensions and scaled dimensions to the appropriate arrays for later reference
			gallery_images.each(function(i){
				img_h[i] = this.height;
				img_w[i] = this.width;

				if(opts.frame_scale=='nocrop') {
					frame_img_scale[i] = Math.min(opts.frame_height/img_h[i],opts.frame_width/img_w[i]);
				} else {
					frame_img_scale[i] = Math.max(opts.frame_height/img_h[i],opts.frame_width/img_w[i]);
				}

				if(opts.panel_scale=='nocrop') {
					panel_img_scale[i] = Math.min(opts.panel_height/img_h[i],opts.panel_width/img_w[i]);
				} else {
					panel_img_scale[i] = Math.max(opts.panel_height/img_h[i],opts.panel_width/img_w[i]);
				}
			});

			// Set gallery dimensions
			j_gallery.css({
				position:'relative',
				width:gallery_width+'px',
				height:gallery_height+'px'
			});

			// Build filmstrip if necessary
			if(opts.show_filmstrip) {
				buildFilmstrip();
				enableFrameClicking();
			}

			//Strip out panel overlays if the user does not want to display them
			if(!opts.show_overlays) {
				$('.gv-panel-overlay',j_gallery).remove();
			}

			// Build panels if necessary
			if(opts.show_panels) {
				buildPanels();
			}

			// If user opts to pause on hover, or no filmstrip exists, add some mouseover functionality
			if(opts.pause_on_hover || opts.show_panel_nav) {
				$(document).mousemove(function(e){

					// If user wants to pause on hover and mouse is over the gallery, halt any animations
					if(opts.pause_on_hover) {
						if(mouseIsOverGallery(e.pageX,e.pageY) && !paused) {
							// Pause slideshow in 500ms. This allows for brief swipes of the mouse over the gallery without unnecessarily pausing it
							$(document).oneTime(500,"animation_pause",function(){
								$(document).stopTime("transition");
								paused=true;
							});
						} else {
							$(document).stopTime("animation_pause");
							if(paused && opts.transition_interval > 0) {
								$(document).everyTime(opts.transition_interval,"transition",function(){
									showNextItem();
								});
								paused = false;
							}
						}
					}

					// If panel navigation is turned on, display or hide it based on mouse position
					if(opts.show_panel_nav) {
						if(mouseIsOverPanel(e.pageX,e.pageY) && !panel_nav_displayed) {
							$('.gv-panel-nav-next, .gv-panel-nav-prev',j_gallery).show();
							panel_nav_displayed = true;
						} else if(!mouseIsOverPanel(e.pageX,e.pageY) && panel_nav_displayed) {
							$('.gv-panel-nav-next, .gv-panel-nav-prev',j_gallery).hide();
							panel_nav_displayed = false;
						}
					}
				});
			}

			// Hide loading box and display gallery
			j_filmstrip.css('visibility','visible');
			j_gallery.css('visibility','visible');

			// Show the 'first' item and then fade out the loader box and begin slideshow timer if necessary
			showItem(iterator,10,function(){
				$('.gv-loader',j_gallery).fadeOut('1000',function(){

					// If we have more than one item, begin automated transitions
					if(item_count > 1 && opts.transition_interval > 0) {
						$(document).everyTime(opts.transition_interval,"transition",function(){
							showNextItem();
						});
					}
				});
			});


		};

	/*
	**	MAIN PLUGIN CODE
	*/
		return this.each(function() {

			// Get UL passed to plugin
			var _t = $(this);

			// Hide the unstyled UL until we've created the gallery
			_t.css('visibility','hidden');

			// Reference images for later use (we'll wait for each to load before building gallery)
			gallery_images = $('img',_t);
			image_count = gallery_images.length;

			// Set the current frame index to that chosen by the user
			// current is 0-based and opts.start_frame is 1-based
			current = opts.start_frame-1;

			// Wrap UL in DIV and transfer ID to container DIV
			_t.wrap("<div></div>");
			j_gallery = _t.parent();
			j_gallery.css('visibility','hidden').attr('id',_t.attr('id')).addClass('gv-gallery').addClass(_t.attr('class'));

			// Assign filmstrip class to the UL sent to the plugin
			_t.removeAttr('id').addClass('gv-filmstrip');

			// If the transition or pause timers exist for any reason, stop them now.
			$(document).stopTime("transition");
			$(document).stopTime("animation_pause");

			// Save the id of the UL passed to the plugin
			id = j_gallery.attr('id');

			// If the UL does not contain any <div class="gv-panel-content"> elements, we will scale the UL images to fill the panels
			scale_panel_images = $('.gv-panel-content',j_gallery).length==0;

			animate_panels = (opts.panel_animation != 'none');

			// Determine filmstrip orientation (vertical or horizontal)
			filmstrip_orientation = (opts.filmstrip_position=='top'||opts.filmstrip_position=='bottom'?'horizontal':'vertical');

			// Do not show captions on vertical filmstrips (override user set option)
			if(filmstrip_orientation=='vertical') { opts.show_captions = false; }


			// Make sure pointer does not extend past width of frame
			if(filmstrip_orientation == 'horizontal' && opts.pointer_size > opts.frame_width/2) {
				opts.pointer_size = opts.frame_width/2;
			}
			if(filmstrip_orientation == 'vertical' && opts.pointer_size > opts.frame_height/2) {
				opts.pointer_size = opts.frame_height/2;
			}


			// Assign elements to variables to minimize calls to jQuery
			j_filmstrip = $('.gv-filmstrip',j_gallery);
			j_frames = $('li',j_filmstrip);
			j_frames.addClass('gv-frame');
			j_panel_wrapper = $('<div>');
			j_panel_wrapper.addClass('gv-panel-wrap').prependTo(j_gallery);

			// If the user wants panels, generate them using the filmstrip images
			if(opts.show_panels) {
				for(i=j_frames.length-1;i>=0;i--) {
					jf = j_frames.eq(i);
					if(jf.find('.gv-panel-content').length>0) {
						jf.find('.gv-panel-content').remove().prependTo(j_panel_wrapper).addClass('gv-panel').addClass(jf.attr('class')).removeClass('gv-frame');
					} else {
						p = $('<div>');
						p.addClass('gv-panel');
						p.addClass(jf.attr('class')).removeClass('gv-frame');
						im = $('<img />');
						jfimg = jf.find('img').eq(0)
						im.attr('src',jfimg.attr('src'));
						if(jfimg.parent('a').length > 0){
							ima = $('<a></a>');
							ima.attr('href',jfimg.parent('a').eq(0).attr('href'));
							ima.attr('target',jfimg.parent('a').eq(0).attr('target'));
							ima.append(im);
							ima.appendTo(p);
						} else {
							im.appendTo(p);
						}
						p.prependTo(j_panel_wrapper);
						j_frames.eq(i).find('.gv-panel-overlay').remove().appendTo(p);
					}
				}
			} else {
				$('.gv-panel-overlay',j_frames).remove();
				$('.gv-panel-content',j_frames).remove();
			}

			// If the user doesn't want a filmstrip, delete it
			if(!opts.show_filmstrip) { j_filmstrip.remove(); }
			else {
				// Wrap the frame images (and links, if applicable) in container divs
				// These divs will handle cropping and zooming of the images
				j_frames.each(function(i){
					if($(this).find('a').length>0) {
						$(this).find('a').wrap('<div class="gv-img-wrap"></div>');
					} else {
						$(this).find('img').wrap('<div class="gv-img-wrap"></div>');
					}
				});
				j_frame_img_wrappers = $('.gv-img-wrap',j_frames);
			}

			j_panels = $('.gv-panel',j_gallery);

			if(!opts.show_panels) {
				opts.panel_height = 0;
				opts.panel_width = 0;
			}

			// Briefly create a caption element so galleryView can determine any padding or borders applied by the user
			$('<div class="gv-caption"></div>').appendTo(j_frames);

			// Determine final frame dimensions, accounting for user-added padding and border
			f_frame_width = opts.frame_width+extraWidth(j_frame_img_wrappers);
			f_frame_height = opts.frame_height+extraHeight(j_frame_img_wrappers);
			frame_caption_size = getInt($('.gv-caption',j_gallery).css('height'));
			f_caption_width = f_frame_width - extraWidth($('.gv-caption',j_gallery));
			f_caption_height = frame_caption_size + extraHeight($('.gv-caption',j_gallery));

			// Delete the temporary caption element
			$('.gv-caption',j_gallery).remove();

			// Number of frames in filmstrip
			item_count = opts.show_panels?j_panels.length:j_frames.length;

			// Number of frames that can display within the gallery block
			// 64 = width of block for navigation button * 2 + 20
			if(filmstrip_orientation=='horizontal') {
				strip_size = opts.show_panels?Math.floor((opts.panel_width+opts.frame_gap-(!opts.show_filmstrip_nav?0:(opts.frame_gap+22)*2))/(f_frame_width+opts.frame_gap)):Math.min(item_count,opts.filmstrip_size);
			} else {
				strip_size = opts.show_panels?Math.floor((opts.panel_height+opts.frame_gap-(!opts.show_filmstrip_nav?0:opts.frame_gap+22))/(f_frame_height+opts.frame_gap)):Math.min(item_count,opts.filmstrip_size);
			}

			// Determine animation method for filmstrip
			// If more items than strip size, slide filmstrip
			// Otherwise, slide pointer
			if(strip_size >= item_count) {
				slide_method = 'pointer';
				strip_size = item_count;
			}
			else {
				slide_method = 'strip';
			}

			// Do not show pointer if there are multiple rows in the filmstrip
			if(Math.ceil(item_count/strip_size) > 1) { opts.pointer_size = 0; }

			// Define dimensions of pointer <div>
			pointer_height = opts.pointer_size;
			pointer_width = opts.pointer_size*2;

			iterator = opts.start_frame-1;
			if(opts.filmstrip_style == 'scroll' && strip_size < item_count) {
				iterator += item_count;
			}

			// Determine dimensions of various gallery elements
			//_filmstrip_margin = (opts.show_panels?getInt(j_filmstrip.css('marginTop')):0);
			j_filmstrip.css('margin',0);

			// Width of filmstrip
			if(filmstrip_orientation=='horizontal') {
				if(opts.filmstrip_style == 'show all' || (opts.filmstrip_style == 'scroll' && slide_method == 'pointer')) {
					strip_width = (f_frame_width*strip_size)+(opts.frame_gap*(strip_size));
				}
				else {
					strip_width = (f_frame_width*item_count*3)+(opts.frame_gap*((item_count*3)));
				}
			} else {
				if(opts.filmstrip_style == 'show all') {
					strip_width = (f_frame_width*Math.ceil(item_count/strip_size))+(opts.frame_gap*(Math.ceil(item_count/strip_size)));
				} else {
					strip_width = (f_frame_width);
				}
			}

			// Height of filmstrip
			if(filmstrip_orientation=='horizontal') {
				if(opts.filmstrip_style == 'show all') {
					strip_height = ((f_frame_height+(opts.show_captions?f_caption_height:0))*Math.ceil(item_count/strip_size))+(opts.frame_gap*(Math.ceil(item_count/strip_size)-1));
				} else {
					strip_height = (f_frame_height+(opts.show_captions?f_caption_height:0));
				}
			} else {
				if(opts.filmstrip_style =='show all' || (opts.filmstrip_style == 'scroll' && slide_method == 'pointer')) {
					strip_height = ((f_frame_height*strip_size)+opts.frame_gap*(strip_size-1));
				}
				else {
					strip_height = (f_frame_height*item_count*3)+(opts.frame_gap*((item_count*3)-1));
				}
			}

			// Width of filmstrip wrapper (to hide overflow)
			if(filmstrip_orientation=='horizontal') {
				wrapper_width = ((strip_size*f_frame_width)+((strip_size-1)*opts.frame_gap));
				if(opts.filmstrip_style == 'show all') {
					wrapper_height = ((f_frame_height+(opts.show_captions?f_caption_height:0))*Math.ceil(item_count/strip_size))+(opts.frame_gap*(Math.ceil(item_count/strip_size)-1));
				} else {
					wrapper_height = (f_frame_height+(opts.show_captions?f_caption_height:0));
				}
			} else {
				wrapper_height = ((strip_size*f_frame_height)+((strip_size-1)*opts.frame_gap));
				if(opts.filmstrip_style == 'show all') {
					wrapper_width = (f_frame_width*Math.ceil(item_count/strip_size))+(opts.frame_gap*(Math.ceil(item_count/strip_size)-1));
				} else {
					wrapper_width = f_frame_width;
				}
			}

			// There shouldn't be any padding on the gallery element
			j_gallery.css('padding',0);

			// Determine final dimensions of gallery
			if(filmstrip_orientation=='horizontal') {

				// Width of gallery block
				gallery_width = opts.show_panels?opts.panel_width:wrapper_width+44+(opts.frame_gap*2);

				// Height of gallery block = screen + filmstrip + captions (optional)
				gallery_height = (opts.show_panels?opts.panel_height+(opts.show_filmstrip?opts.frame_gap:0):0)+(opts.show_filmstrip?wrapper_height:0);
			} else {

				// Width of gallery block
				gallery_height = opts.show_panels?opts.panel_height:wrapper_height+22;

				// Height of gallery block = screen + filmstrip + captions (optional)
				gallery_width = (opts.show_panels?opts.panel_width+(opts.show_filmstrip?opts.frame_gap:0):0)+(opts.show_filmstrip?wrapper_width:0);
			}

			// Place loading box over gallery until page loads
			galleryPos = getPos(j_gallery[0]);
			$('<div>').addClass('gv-loader').css({
				position:'absolute',
				zIndex:'32666',
				opacity:1,
				top:0,
				left:0,
				width:gallery_width+'px',
				height:gallery_height+'px'
			}).appendTo(j_gallery);

			// We don't want to move to the next frame before the current one is done loading
			// If the animation speed is greater than the delay between animations, set them equal
			if(opts.transition_speed > opts.transition_interval && opts.transition_interval > 0) {
				opts.transition_speed = opts.transition_interval;
			}

			// Set pointer animation speed based on user options
			pointer_speed = opts.animate_pointer ? opts.transition_speed : 0;

			// Build gallery as soon as all images are loaded or pulled from cache
			if(!window_loaded) {
				gallery_images.each(function(i){

					// First, see if image is already loaded (gallery being built after window loads or image is pulled from cache)
					if($(this).attr('complete')) {
						loaded_images++;
						if(loaded_images==image_count) {
							buildGallery();
							window_loaded;
						}
					} else {

						// Otherwise, increment counter once image loads
						$(this).load(function(){
							loaded_images++;
							if(loaded_images==image_count) {
								buildGallery();
								window_loaded;
							}
						});
					}
				});
			} else {
				buildGallery();
			}
		});
	};

/*
**	GalleryView options and default values
*/
	$.fn.galleryView.defaults = {

		transition_speed: 800,				//INT - duration of panel/frame transition (in milliseconds)
		transition_interval: 4000,			//INT - delay between panel/frame transitions (in milliseconds)
		easing: 'swing',					//STRING - easing method to use for animations (jQuery provides 'swing' or 'linear', more available with jQuery UI or Easing plugin)
		pause_on_hover: false,				//BOOLEAN - flag to pause slideshow when user hovers over the gallery


		show_panels: true,					//BOOLEAN - flag to show or hide panel portion of gallery
		panel_width: 600,					//INT - width of gallery panel (in pixels)
		panel_height: 400,					//INT - height of gallery panel (in pixels)
		panel_animation: 'crossfade',		//STRING - animation method for panel transitions (crossfade,fade,slide,zoomOut,none)
		overlay_opacity: 0.7,				//FLOAT - transparency for panel overlay (1.0 = opaque, 0.0 = transparent)
		overlay_position: 'bottom',			//STRING - position of panel overlay (bottom, top)
		panel_scale: 'crop',				//STRING - cropping option for panel images (crop = scale image and fit to aspect ratio determined by panel_width and panel_height, nocrop = scale image and preserve original aspect ratio)
		show_panel_nav: true,				//BOOLEAN - flag to show or hide panel navigation buttons
		show_overlays: false,				//BOOLEAN - flag to show or hide panel overlays


		show_filmstrip: true,				//BOOLEAN - flag to show or hide filmstrip portion of gallery
		frame_width: 60,					//INT - width of filmstrip frames (in pixels)
		frame_height: 40,					//INT - width of filmstrip frames (in pixels)
		start_frame: 1,						//INT - index of panel/frame to show first when gallery loads
		filmstrip_size: 3,					//INT - number of frames to show in filmstrip-only gallery
		frame_opacity: 0.3,					//FLOAT - transparency of non-active frames (1.0 = opaque, 0.0 = transparent)
		filmstrip_style: 'scroll',			//STRING - type of filmstrip to use (scroll, show all)
		filmstrip_position: 'bottom',		//STRING - position of filmstrip within gallery (bottom, top, left, right)
		show_filmstrip_nav: true,			//BOOLEAN - flag indicating whether to display navigation buttons
		frame_scale: 'crop',				//STRING - cropping option for filmstrip images (same as above)
		frame_gap: 5,						//INT - spacing between frames within filmstrip (in pixels)
		show_captions: false,				//BOOLEAN - flag to show or hide frame captions


		pointer_size: 8,					//INT - Height of frame pointer (in pixels)
		animate_pointer: true				//BOOLEAN - flag to animate pointer or move it instantly to target frame

	};
})(jQuery);
;
/**
 * @file
 * Javascript for the student custom module.
 */
(function ($) {

Drupal.behaviors.studentCustom = {
  attach: function (context) {

    $('#block-pirg-custom-pirg-home-features').once('pirg-gallery', function () {
      // Remove the extra <div class="field-collection-view"> inside each list item.
      $(this).find('ul.field-name-field-home-featured-articles > li.field-item > div.field-collection-view').each(function() {
        $(this).parent().html($(this).html());
      });

      // Give the block an id for the gallery to work on.
      $(this).find('ul.field-name-field-home-featured-articles').attr('id', 'pirg-gallery');

      // Create the gallery.
      $('#pirg-gallery').galleryView({
        pause_on_hover: true,
        panel_width: 660,
        panel_height: 269,
        frame_width: 140,
        frame_height: 20,
        show_overlays: true,
        show_panels: true,
        filmstrip_position: 'top',
        nav_theme: 'dark',
        easing: 'swing',
        overlay_opacity: 0.6,
        overlay_color: 'black',
        background_color: 'black',
        background_fill_color: 'black',
        overlay_text_color: 'white',
        caption_text_color: 'white',
        border: 'none',
        show_captions: true,
        show_filmstrip_nav: false,
        pointer_size: 0,
        animate_pointer: false,
        transition_interval: 8000
      });

      // This has to be delayed through window.load() since that's when
      // the gallery is attached as well.
      $(window).load(function() {
	window.setTimeout(function() {
          $('#pirg-gallery .gv-caption, #pirg-gallery .gv-strip-wrapper').attr('style', '');
          $('#pirg-gallery .gv-strip-wrapper .gv-img-wrap').remove();
	}, 10);
      });
    });
  }
};
})(jQuery);
;
/*
 * 	Easy Slider - jQuery plugin
 *	written by Alen Grakalic	
 *	http://cssglobe.com/post/3783/jquery-plugin-easy-image-or-content-slider
 *
 *	Copyright (c) 2009 Alen Grakalic (http://cssglobe.com)
 *	Dual licensed under the MIT (MIT-LICENSE.txt)
 *	and GPL (GPL-LICENSE.txt) licenses.
 *
 *	Built for jQuery library
 *	http://jquery.com
 *
 */
 
/*
 *	markup example for $("#images").easySlider();
 *	
 * 	<div id="images">
 *		<ul>
 *			<li><img src="images/01.jpg" alt="" /></li>
 *			<li><img src="images/02.jpg" alt="" /></li>
 *			<li><img src="images/03.jpg" alt="" /></li>
 *			<li><img src="images/04.jpg" alt="" /></li>
 *			<li><img src="images/05.jpg" alt="" /></li>
 *		</ul>
 *	</div>
 *
 */

(function($) {

	$.fn.easySlider = function(options){
	  
		// default configuration properties
		var defaults = {
			prevId: 		'prevBtn',
			prevText: 		'Previous',
			nextId: 		'nextBtn',	
			nextText: 		'Next',
			orientation:	'', //  'vertical' is optional;
			speed: 			800			
		}; 
		
		var options = $.extend(defaults, options);  
		
		return this.each(function() {  
			obj = $(this); 				
			var s = $("li", obj).length;
			var w = obj.width(); 
			var h = obj.height(); 
			var ts = s-1;
			var t = 0;
			var vertical = (options.orientation == 'vertical');
			$("ul", obj).css('width',s*w);			
			if(!vertical) $("li", obj).css('float','left');
			$(obj).after('<span id="'+ options.prevId +'"><a href=\"javascript:void(0);\">'+ options.prevText +'</a></span> <span id="'+ options.nextId +'"><a href=\"javascript:void(0);\">'+ options.nextText +'</a></span>');		
			$("a","#"+options.prevId).hide();
			$("a","#"+options.nextId).hide();
			$("a","#"+options.nextId).click(function(){		
				animate("next");
				if (t>=ts) $(this).fadeOut();
				$("a","#"+options.prevId).fadeIn();
			});
			$("a","#"+options.prevId).click(function(){		
				animate("prev");
				if (t<=0) $(this).fadeOut();
				$("a","#"+options.nextId).fadeIn();
			});	
			function animate(dir){
				if(dir == "next"){
					t = (t>=ts) ? ts : t+1;	
				} else {
					t = (t<=0) ? 0 : t-1;
				};								
				if(!vertical) {
					p = (t*w*-1);
					$("ul",obj).animate(
						{ marginLeft: p }, 
						options.speed
					);				
				} else {
					p = (t*h*-1);
					$("ul",obj).animate(
						{ marginTop: p }, 
						options.speed
					);					
				}
			};
			if(s>1) $("a","#"+options.nextId).fadeIn();	
		});
	  
	};

})(jQuery);;

