/* Minification failed. Returning unminified contents.
(1458,55-56): run-time error JS1195: Expected expression: >
(1463,12-13): run-time error JS1195: Expected expression: )
(1465,9-13): run-time error JS1009: Expected '}': else
(1465,9-13): run-time error JS1034: Unmatched 'else'; no 'if' defined: else
(1465,41-42): run-time error JS1004: Expected ';': {
(1471,7-8): run-time error JS1002: Syntax error: }
(1476,38-39): run-time error JS1004: Expected ';': {
(1519,6-7): run-time error JS1195: Expected expression: ,
(1523,35-36): run-time error JS1195: Expected expression: )
(1523,37-38): run-time error JS1004: Expected ';': {
(1558,6-7): run-time error JS1195: Expected expression: ,
(1560,47-48): run-time error JS1004: Expected ';': {
(1578,6-7): run-time error JS1195: Expected expression: ,
(1591,32-33): run-time error JS1195: Expected expression: )
(1591,34-35): run-time error JS1004: Expected ';': {
(1594,6-7): run-time error JS1195: Expected expression: ,
(1596,32-33): run-time error JS1004: Expected ';': {
(1599,6-7): run-time error JS1195: Expected expression: ,
(1602,16-17): run-time error JS1197: Too many errors. The file might not be a JavaScript file: :
(1593,7-64): run-time error JS1018: 'return' statement outside of function: return $($(".ais-image-filename-value").get(index)).val()
 */
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(2($){$.c.f=2(p){p=$.d({g:"!@#$%^&*()+=[]\\\\\\\';,/{}|\\":<>?~`.- ",4:"",9:""},p);7 3.b(2(){5(p.G)p.4+="Q";5(p.w)p.4+="n";s=p.9.z(\'\');x(i=0;i<s.y;i++)5(p.g.h(s[i])!=-1)s[i]="\\\\"+s[i];p.9=s.O(\'|\');6 l=N M(p.9,\'E\');6 a=p.g+p.4;a=a.H(l,\'\');$(3).J(2(e){5(!e.r)k=o.q(e.K);L k=o.q(e.r);5(a.h(k)!=-1)e.j();5(e.u&&k==\'v\')e.j()});$(3).B(\'D\',2(){7 F})})};$.c.I=2(p){6 8="n";8+=8.P();p=$.d({4:8},p);7 3.b(2(){$(3).f(p)})};$.c.t=2(p){6 m="A";p=$.d({4:m},p);7 3.b(2(){$(3).f(p)})}})(C);',53,53,'||function|this|nchars|if|var|return|az|allow|ch|each|fn|extend||alphanumeric|ichars|indexOf||preventDefault||reg|nm|abcdefghijklmnopqrstuvwxyz|String||fromCharCode|charCode||alpha|ctrlKey||allcaps|for|length|split|1234567890|bind|jQuery|contextmenu|gi|false|nocaps|replace|numeric|keypress|which|else|RegExp|new|join|toUpperCase|ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('|'),0,{}));
;
/**
 * jQuery Plugin to obtain touch gestures from iPhone, iPod Touch and iPad, should also work with Android mobile phones (not tested yet!)
 * Common usage: wipe images (left and right to show the previous or next image)
 * 
 * @author Andreas Waltl, netCU Internetagentur (http://www.netcu.de)
 * @version 1.1.1 (9th December 2010) - fix bug (older IE's had problems)
 * @version 1.1 (1st September 2010) - support wipe up and wipe down
 * @version 1.0 (15th July 2010)
 */
(function($) { 
   $.fn.touchwipe = function(settings) {
     var config = {
    		min_move_x: 20,
    		min_move_y: 20,
 			wipeLeft: function() { },
 			wipeRight: function() { },
 			wipeUp: function() { },
 			wipeDown: function() { },
			preventDefaultEvents: true
	 };
     
     if (settings) $.extend(config, settings);
 
     this.each(function() {
    	 var startX;
    	 var startY;
		 var isMoving = false;

    	 function cancelTouch() {
    		 this.removeEventListener('touchmove', onTouchMove);
    		 startX = null;
    		 isMoving = false;
    	 }	
    	 
    	 function onTouchMove(e) {
    		 if(config.preventDefaultEvents) {
    			 e.preventDefault();
    		 }
    		 if(isMoving) {
	    		 var x = e.touches[0].pageX;
	    		 var y = e.touches[0].pageY;
	    		 var dx = startX - x;
	    		 var dy = startY - y;
	    		 if(Math.abs(dx) >= config.min_move_x) {
	    			cancelTouch();
	    			if(dx > 0) {
	    				config.wipeLeft();
	    			}
	    			else {
	    				config.wipeRight();
	    			}
	    		 }
	    		 else if(Math.abs(dy) >= config.min_move_y) {
		    			cancelTouch();
		    			if(dy > 0) {
		    				config.wipeDown();
		    			}
		    			else {
		    				config.wipeUp();
		    			}
		    		 }
    		 }
    	 }
    	 
    	 function onTouchStart(e)
    	 {
    		 if (e.touches.length === 1) {
    			 startX = e.touches[0].pageX;
    			 startY = e.touches[0].pageY;
    			 isMoving = true;
    			 this.addEventListener('touchmove', onTouchMove, false);
    		 }
    	 }    	 
    	 if ('ontouchstart' in document.documentElement) {
    		 this.addEventListener('touchstart', onTouchStart, false);
    	 }
     });
 
     return this;
   };
 
 })(jQuery);
;
(function(a){function g(a){a.setFullYear(2001),a.setMonth(0),a.setDate(0);return a}function f(a,b){if(a){var c=a.split(b.separator),d=parseFloat(c[0]),e=parseFloat(c[1]);b.show24Hours||(d===12&&a.indexOf("AM")!==-1?d=0:d!==12&&a.indexOf("PM")!==-1&&(d+=12));var f=new Date(0,0,0,d,e,0);return g(f)}return null}function e(a,b){return typeof a=="object"?g(a):f(a,b)}function d(a){return(a<10?"0":"")+a}function c(a,b){var c=a.getHours(),e=b.show24Hours?c:(c+11)%12+1,f=a.getMinutes();return d(e)+b.separator+d(f)+(b.show24Hours?"":c<12?" AM":" PM")}function b(b,c,d,e){b.value=a(c).text(),a(b).change(),a.browser.msie||b.focus(),d.hide()}a.fn.timePicker=function(b){var c=a.extend({},a.fn.timePicker.defaults,b);return this.each(function(){a.timePicker(this,c)})},a.timePicker=function(b,c){var d=a(b)[0];return d.timePicker||(d.timePicker=new jQuery._timePicker(d,c))},a.timePicker.version="0.3",a._timePicker=function(d,h){var i=!1,j=!1,k=e(h.startTime,h),l=e(h.endTime,h),m="selected",n="li."+m;a(d).attr("autocomplete","OFF");var o=[],p=new Date(k);while(p<=l)o[o.length]=c(p,h),p=new Date(p.setMinutes(p.getMinutes()+h.step));var q=a('<div class="time-picker'+(h.show24Hours?"":" time-picker-12hours")+'"></div>'),r=a("<ul></ul>");for(var s=0;s<o.length;s++)r.append("<li>"+o[s]+"</li>");q.append(r),q.appendTo("body").hide(),q.mouseover(function(){i=!0}).mouseout(function(){i=!1}),a("li",r).mouseover(function(){j||(a(n,q).removeClass(m),a(this).addClass(m))}).mousedown(function(){i=!0}).click(function(){b(d,this,q,h),i=!1});var t=function(){if(q.is(":visible"))return!1;a("li",q).removeClass(m);var b=a(d).offset();q.css({top:b.top+d.offsetHeight,left:b.left}),q.show();var e=d.value?f(d.value,h):k,i=k.getHours()*60+k.getMinutes(),j=e.getHours()*60+e.getMinutes()-i,n=Math.round(j/h.step),o=g(new Date(0,0,0,0,n*h.step+i,0));o=k<o&&o<=l?o:k;var p=a("li:contains("+c(o,h)+")",q);p.length&&(p.addClass(m),q[0].scrollTop=p[0].offsetTop);return!0};a(d).focus(t).click(t),a(d).blur(function(){i||q.hide()});var u=a.browser.opera||a.browser.mozilla?"keypress":"keydown";a(d)[u](function(c){var e;j=!0;var f=q[0].scrollTop;switch(c.keyCode){case 38:if(t())return!1;e=a(n,r);var g=e.prev().addClass(m)[0];g?(e.removeClass(m),g.offsetTop<f&&(q[0].scrollTop=f-g.offsetHeight)):(e.removeClass(m),g=a("li:last",r).addClass(m)[0],q[0].scrollTop=g.offsetTop-g.offsetHeight);return!1;case 40:if(t())return!1;e=a(n,r);var i=e.next().addClass(m)[0];i?(e.removeClass(m),i.offsetTop+i.offsetHeight>f+q[0].offsetHeight&&(q[0].scrollTop=f+i.offsetHeight)):(e.removeClass(m),i=a("li:first",r).addClass(m)[0],q[0].scrollTop=0);return!1;case 13:if(q.is(":visible")){var k=a(n,r)[0];b(d,k,q,h)}return!1;case 27:q.hide();return!1}return!0}),a(d).keyup(function(a){j=!1}),this.getTime=function(){return f(d.value,h)},this.setTime=function(b){d.value=c(e(b,h),h),a(d).change()}},a.fn.timePicker.defaults={step:30,startTime:new Date(0,0,0,0,0,0),endTime:new Date(0,0,0,23,30,0),separator:":",show24Hours:!0}})(jQuery);
/// <reference path="~/Scripts/External/jquery.ui.autocomplete.js" />
/// <reference path="~/Scripts/External/jquery-ui.min.js" />

"use strict";
if (typeof (AIS) !== "object") { var AIS = new Object(); }

AIS.Mobile = function () {
  var openMenu = false;
  function toggleMenu() {
    document.body.classList.toggle('noscroll');
    if (!openMenu) {
      stopBodyScrolling(true, true);
      $("#mobile-inner-menu").slideDown(300);
    } else {
      stopBodyScrolling(false, true);
      $("#mobile-inner-menu").slideUp(300);
    }
    openMenu = !openMenu;
  }
  var languageSelectionOpen = false;
  function toggleLanguageSelection() {
    document.body.classList.toggle('noscroll');
    if (!languageSelectionOpen) {
      stopBodyScrolling(true, false);
      $("#mobile-language-chooser").fadeIn(300);
    } else {
      stopBodyScrolling(false, false);
      $("#mobile-language-chooser").fadeOut(300);
    }
    languageSelectionOpen = !languageSelectionOpen;
  }
  function stopBodyScrolling(bool, completely) {
    var element = document.getElementById("ais-master");
    var body = document.body;
    if (bool) {
      element.addEventListener("touchmove", freezeBody);
      if (completely) {
        body.addEventListener("touchmove", freezeBody, true);
      }

    } else {
      element.removeEventListener("touchmove", freezeBody);
      if (completely) {
        body.removeEventListener("touchmove", freezeBody, true);
      }
    }
  }
  function freezeBody(e) {
    e.preventDefault();
  }
  function init() {
    document.getElementById("ais-master").addEventListener("touchmove", onMove, false);
  }
  function onMove(e) {

    var element = document.body;
    if (element.offsetHeight > element.scrollHeight) {
      e.preventDefault();
    }
  }
  init();
  return {
    ToggleMenu: toggleMenu,
    ToggleLanguageSelection: toggleLanguageSelection
  }
}();

AIS.Tooltip = function () {

  var _tooltip = null;
  var _element = null;

  var show = function (element) {
    _element = element;
    var data = element.getAttribute("data-tooltip");
    _tooltip = document.createElement("div");
    _tooltip.setAttribute("class", "tooltip");
    _tooltip.innerHTML = data;
    element.appendChild(_tooltip);
  }

  var hide = function () {
    _element.removeChild(_tooltip);
  }

  return {
    Show: show,
    Hide: hide
  }
}();
AIS.Storage = function () {
  var memoryStorage = {};

  function get(key) {
    if (typeof localStorage !== 'undefined') {
      return JSON.parse(localStorage.getItem(key));
    } else {
      return memoryStorage[key];
    }
  };

  function set(key, value) {
    if (typeof localStorage !== 'undefined') {
      localStorage.setItem(key, JSON.stringify(value));
    } else {
      memoryStorage[key] = value;
    }
  };

  function remove(key) {
    if (typeof localStorage !== 'undefined') {
      localStorage.removeItem(key);
    } else {
      delete memoryStorage[key];
    }
  }

  return {
    Get: get,
    Set: set,
    Remove: remove
  }
}();

AIS.Helpers = function () {

  return {
    Show: function (element) {
      var parent = $(element).parentsUntil("toggle-group.container");
      parent.children(".toggle-group.show-label").hide();
      parent.children(".toggle-group.hide-label").show().css({ 'display': 'inline-block', 'margin-right': '2px' });
      parent.children(".toggle-group.children").slideToggle("fast");
    },

    Hide: function (element) {
      var parent = $(element).parentsUntil("toggle-group.container");
      parent.children(".toggle-group.show-label").show();
      parent.children(".toggle-group.hide-label").hide();
      parent.children(".toggle-group.children").slideToggle("fast");
    },
    ResolveUrl: function (relativePath) {
      var baseUrl = $("#ais-base-url").val();
      return AIS.Helpers.Rtrim(baseUrl, "/") + "/" + AIS.Helpers.Ltrim(relativePath, "/");
    },

    Rtrim: function (str, chars) {
      chars = chars || "\\s";
      return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
    },

    Ltrim: function (str, chars) {
      chars = chars || "\\s";
      return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
    },

    Trim: function (str, chars) {
      return AIS.Helpers.Rtrim(AIS.Helpers.Ltrim(str, chars));
    },

    EscapeSelectorExpression: function (expression) {
      // Special characters defined here: http://api.jquery.com/category/selectors/
      // Must be escaped with two backslashes, i.e. '\\'
      if (expression) {
        return expression.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/@])/g, '\\$1');
      }
      return expression;
    },

    //generic AddUserMessage function
    AddUserMessage: function (message, type, temporary, translate) {

      $.ajax({
        type: "get",
        url: AIS.Helpers.ResolveUrl("helper/getusermessage"),
        dataType: "html",
        data: {
          message: message,
          type: type,
          translate: translate,
          temporary: temporary
        },
        success: function (data) {
          //add the markup to the user message div
          AIS.Helpers.RemoveUserMessage();

          var currHtml = $(".ais-user-message-element").html();
          $(".ais-user-message-element").html(currHtml + data);
        }
      });
    },

    //Information message
    AddInformationUserMessage: function (message, translate) {
      AIS.Helpers.AddUserMessage(message, "Information", translate);
    },
    AddTempInformationUserMessage: function (message, translate) {
      AIS.Helpers.AddUserMessage(message, "Information", true, translate);
    },

    //Success message
    AddSuccessUserMessage: function (message, translate, temporary) {
      AIS.Helpers.AddUserMessage(message, "Success", translate);
    },
    AddTempSuccessUserMessage: function (message, translate) {
      AIS.Helpers.AddUserMessage(message, "Success", true, translate);
    },

    //Warning message
    AddWarningUserMessage: function (message, translate) {
      AIS.Helpers.AddUserMessage(message, "Warning", translate);
    },
    AddTempWarningUserMessage: function (message, translate) {
      AIS.Helpers.AddUserMessage(message, "Warning", true, translate);
    },

    //Error message
    AddErrorUserMessage: function (message, translate) {
      AIS.Helpers.AddUserMessage(message, "Error", translate);
    },
    AddTempErrorUserMessage: function (message, translate) {
      AIS.Helpers.AddUserMessage(message, "Error", true, translate);
    },

    //Remove user message
    RemoveUserMessage: function () {
      $(".ais-user-message-element").html('');
    },

    //Toggle menu items
    EnableMenuItem: function (itemId) {
      $("#" + itemId).attr("href", $("#" + itemId).parent().children("input.ais-hidden-href-value").val());
      $("#" + itemId).parent().removeClass("disabled");
    },

    DisableMenuItem: function (itemId) {
      $("#" + itemId).removeAttr("href");
      $("#" + itemId).parent().removeClass("active");
      $("#" + itemId).parent().addClass("disabled");
    },

    //Request datepicker
    RequestDatePicker: function () {
      jQuery('input.requestdatepicker').datepicker("destroy");
      var currentYear = (new Date).getFullYear();
      var currentIsoDate = (new Date).toISOString();
      $('select#destination').val("READING_ROOM"); 
      $('input#requested-for-date').val(currentIsoDate.substring(0, currentIsoDate.indexOf("T"))); 
      $('input#expected-return-date').val(currentIsoDate.substring(0, currentIsoDate.indexOf("T"))); 
      $('input.requestdatepicker').datepicker({
        minDate: 0,
        changeYear: true,
        yearRange: (currentYear) + ":"+(currentYear+1),
        dateFormat: "yy-mm-dd",
        showOn: 'button',
        autoclose: true,
        buttonText: "<i class='far fa-calendar-alt'></i>"
        //buttonImage: AIS.Helpers.ResolveUrl("Content/Images/ais-calendar.png"),
        //buttonImageOnly: true
      });
    },

    //Date picker
    AttachDatePicker: function () {
      jQuery('input.datepicker').datepicker("destroy");
      var currentUICultureField = $(".ais-current-ui-culture-value");
      var currentUICulture = "";

      if (currentUICultureField !== null && currentUICultureField !== undefined) {
        currentUICulture = currentUICultureField.val();
      }

      $.datepicker.setDefaults($.datepicker.regional[currentUICulture]);
      var currentYear = (new Date).getFullYear();
      $('input.datepicker').datepicker({
        changeYear: true,
        yearRange: "1900:" + (currentYear),
        dateFormat: "yy-mm-dd",
        showOn: 'button',
        buttonImage: AIS.Helpers.ResolveUrl("Content/Images/ais-calendar.png"),
        buttonImageOnly: true
      });
    },

    //Time picker
    AttachTimePicker: function () {

      $('input.timepicker').timePicker({
        show24Hours: true, // TODO: Use localization
        separator: ':',
        step: 15
      });

    },

    //Set Focus
    SetFocusFirstInput: function (container) {

      //TODO: Review. It's not working in IE for some cases...
      $(container).find("input[type='text']:visible:enabled:first").focus();
    },

    ScrollToTop: function () {
      $('html, body').animate({ scrollTop: '0' }, 50);
    },

    RaiseRequestPrompt: function (sender) {
      AIS.Helpers.RequestDatePicker();
      var destination = sender.attr("destination");
      $('input#expected-return-date').datepicker("disable");
      if (destination == 'USER') {
        //$('input#expected-return-date').datepicker("enable");
        $("#raise-request-dialog #destination").prop("disabled", false);
      }
      $("#raise-request-dialog").dialog({
        resizable: true,
        width: "450px",
        buttons: [
          {
            text: "OK",
            class: "dialog-yes",
            click: function () {
              AIS.Helpers.RaiseRquest(sender);
              $(this).dialog("close");
            }
          },
          {
            text: "Cancel",
            click: function () {
              $(this).dialog().resetForm();
              $(this).dialog("close");
            }
          }
        ]
      });
    },

    RaiseRequestDates: function (sender) {
      var dest = $("#destination").val();
      $("#request-raise-msg").hide().html("");
      var maxissuedays = $(".ais-raise-request-script").attr("max_issue_days");
      // check destination and expected-return-date
      // if destination is rr > update expected-return-date to rfd
      if (dest == "READING_ROOM") {
        $('input#expected-return-date').val($('input#requested-for-date').val());
      } else {
        // erd < tfd  then erd = rfd
        if ($('input#expected-return-date').val() < $('input#requested-for-date').val()) {
          $('input#expected-return-date').val($('input#requested-for-date').val());
        }
        var rfd = new Date($('input#requested-for-date').val());
        var rfd2 = new Date($('input#requested-for-date').val());
        var erd = new Date($('input#expected-return-date').val());
        var erdmax = new Date(rfd2.setDate(rfd2.getDate() + parseInt(maxissuedays)));
        //alert(rfd +"*"+erd+"*"+erdmax);
        if (erd > erdmax) {
          //if ($('input#expected-return-date').val() > $('input#requested-for-date').val() + maxissuedays) {
          $("#request-raise-msg").show();
          $("#request-raise-msg").html("<i style='color:red' class='fas fa-exclamation-circle'></i> Return date cannot be later than " + $.datepicker.formatDate('yy-mm-dd', erdmax))
          $('input#expected-return-date').val($.datepicker.formatDate('yy-mm-dd', erdmax));
        }
      }
    },

    RaiseRquest: function (sender) {
      var itemId = $(sender).attr("itemid");
      var rd = $("#raise-request-dialog #requested-for-date").val();
      var database = $(".ais-request-database-name").val();
      $(sender).append('&nbsp;<i class="fas fa-spinner fa-spin"></i>');

      $.ajax({
        url: AIS.Helpers.ResolveUrl("reservations/raiserequest"),
        data: {
          database: database,
          itemId: itemId,
          requestedDate: rd,
          expectedReturnDate: $("#raise-request-dialog #expected-return-date").val(),
          destination: $("#raise-request-dialog #destination").val()
        },
        success: function (data) {

          if (data.type === 4) { //error
            $(sender).children("span").html("Item not requested");
          }
          else if (data.type === 2) { //success
            $(sender).children("span").html("Item requested");
          }

          if (data.label) {
            $(sender).children("span").html(data.label);
          }

          if (data.message) {
            AIS.Helpers.AddUserMessage(data.message, data.type, true, false);
          }

          $(sender).children('i').remove();
          $(sender).removeClass("ais-create-reservation-script");
          $(sender).removeClass("ais-create-reservation");
          $(sender).addClass("ais-cancel-reservation-script");
          $(sender).addClass("ais-cancel-reservation");
        }
      });
    },

    CreateOrder: function (sender) {
      $("#order-confirm-dialog").dialog({
        buttons: [
          {
            text: "Yes",
            class: "dialog-yes",
            click: function () {
              var userId = $("#ais-borrower-number").val();
              var userInput = $("#order-request-input").val();
              AIS.Helpers.CreateOrderPrompt(sender);
              $(this).dialog("close");
            }
          },
          {
            text: "No",
            click: function () {
              $(this).dialog("close");
            }
          }
        ]
      });
    },
    CreateOrderPrompt: function (sender) {
      var itemId = $(sender).siblings(".ais-item-number-value").val();
      var userId = $(sender).siblings(".ais-user-id-value").val();
      var resource = $(sender).siblings(".ais-resource-value").val();
      var priref = $(sender).parent().children(".record-selector").attr("data-priref");

      sender.append("&nbsp;<i class='fa fa-spinner fa-spin'></i>");

      $.ajax({
        url: AIS.Helpers.ResolveUrl("ordering/createorder"),
        data: {
          itemId: itemId,
          userId: userId,
          resource: resource
        },
        success: function (data) {
          if (data.type === 4) { //error
            $(sender).children("span").html("Item not ordered");
          }
          else if (data.type === 2) { //success
            $(sender).children("span").html("Item ordered");
          }

          if (data.message) {
            AIS.Helpers.AddUserOrderMessage(data.message, data.type, true, false, priref);
          }
          sender.find('i').remove();
          $(sender).removeClass("ais-create-order-script");
          $(sender).addClass("disabled");
        },
        error: function (data) {
          $(sender).children("span").html("Error ordering the item");

          if (data.message) {
            AIS.Helpers.AddUserOrderMessage("Error: " + data.message, data.type, true, false, priref);
          }
          sender.find('i').remove();
          $(sender).removeClass("ais-create-order-script");
          $(sender).addClass("disabled");
        }
      });
    },

    AddUserOrderMessage: function (message, type, temporary, translate, priref) {

      $.ajax({
        type: "get",
        url: AIS.Helpers.ResolveUrl("helper/getusermessage"),
        dataType: "html",
        data: {
          message: message,
          type: type,
          translate: translate,
          temporary: temporary
        },
        success: function (data) {
          //add the markup to the user message div
          AIS.Helpers.RemoveUserMessage();

          var currHtml = $(".ais-user-message-element").html();
          $(".ais-user-message-order-element-" + priref).html(currHtml + data);
          $(".ais-user-message-order-element-" + priref + ">div").addClass("type" + type);
        }
      });
    },

    Translate: function (key) {

      var translation;

      $.ajax({
        type: "get",
        url: AIS.Helpers.ResolveUrl("/helper/translate"),
        async: false,
        data: {
          Key: key
        },
        dataType: "text",
        success: function (data) {
          translation = data;
        }
      });

      return translation;

    }
  }

}();;
AIS.RecordSelection = function () {

  var functions = {};

  functions.GetSelectorsByState = function (state) { return $(document).find(".record-selector[data-selected='" + state + "']"); };

  functions.SelectionCounter = function () { return $("#ais-menu-inner #ais-menu-list #menuSelection .ais-menu-item-tip-element"); };

  functions.SetSelector = function (selector, state) {
    var selectorState = $(selector).attr("data-selected");
    if (selectorState !== state) {
      var count = functions.GetSelectionCounter();
      if (state === "true") {
        functions.SetSelectionCounter(++count);
      }
      else {
        if (count > 0) {
          functions.SetSelectionCounter(--count);
        }
        else return;
      }
      $(selector).attr("data-selected", state);
      $(selector).children(".remove-selection-button").toggle();
      $(selector).children(".add-selection-button").toggle();

    };
  };

  functions.SetSelectors = function (selectors, state) {
    $(selectors).each(function () {
      functions.SetSelector(this, state);
    });
  };

  functions.SelectAll = function () {
    $.ajax({
      url: AIS.Helpers.ResolveUrl("results/selectall"),
      data: {},
      success: function (data) {
        if (data.Success === false) {
          if (data.Message) { AIS.Helpers.AddTempWarningUserMessage(data.Message, false); }
        }
        else {
          var unchecked = functions.GetSelectorsByState("false");
          functions.SetSelectors(unchecked, "true");
          functions.SetSelectionCounter(data.SelectionCounter);
        }
      }
    });
  };

  functions.InvertSelection = function () {
    $.ajax({
      url: AIS.Helpers.ResolveUrl("results/invertselection"),
      data: {},
      success: function (data) {
        if (data.Success === false) {
          if (data.Message) { AIS.Helpers.AddTempWarningUserMessage(data.Message, false); }
        }
        else {
          var selectorsToCheck = functions.GetSelectorsByState("false");
          var selectorsToUncheck = functions.GetSelectorsByState("true");
          functions.SetSelectors(selectorsToCheck, "true");
          functions.SetSelectors(selectorsToUncheck, "false");
          functions.SetSelectionCounter(data.SelectionCounter);
        }
      }
    });
  };

  functions.ClearSelection = function () {
    $.ajax({
      url: AIS.Helpers.ResolveUrl("results/clearselection"),
      data: {},
      success: function (data) {
        if (data.Success === false) {
          if (data.Message) { AIS.Helpers.AddTempWarningUserMessage(data.Message, false); }
        }
        else {
          var selected = functions.GetSelectorsByState("true");
          functions.SetSelectors(selected, "false");
          functions.SetSelectionCounter(0);
        }
      }
    });
  };

  //Toggle selection menu item specifically
  functions.EnableSelectionMenuItem = function () {
    var items = $("#ais-menu-item-menuSelection a");
    items.each(function () {
      parent = $(this).parent();
      //parent.removeClass("disabled");
      $(this).parent().attr("class","ais-menu-item");
      $(this).attr("href", $(this).parent().children("input.ais-hidden-href-value").val());
    });
  };
  //disable the selection button in the menu (and the mobile version)
  functions.DisableSelectionMenuItem = function () {
    var items = $("#ais-menu-item-menuSelection a");
    items.each(function () {
      var parent = $(this).parent();
      $(this).removeAttr("href");
      parent.removeClass("active");
      parent.addClass("disabled");
    });
  };

  functions.AddToSelection = function (priref, database, sitename, record) {
    $.ajax({
      url: AIS.Helpers.ResolveUrl("results/addtoselection"),
      data: {
        priref: priref,
        database: database,
        sitename: sitename
      },
      success: function (data) {
        if (data.Success === false) {
          if (data.Message) {
            AIS.Helpers.AddTempWarningUserMessage(data.Message, false);
          }
        }
        else {
          functions.SetSelector(record, "true");
        }
      }
    });
  };

  functions.RemoveFromSelection = function (priref, database, sitename, record) {
    $.ajax({
      url: AIS.Helpers.ResolveUrl("results/removefromselection"),
      data: {
        priref: priref,
        database: database,
        sitename: sitename
      },
      success: function (data) {
        if (data.Success === false) {
          if (data.Message) { AIS.Helpers.AddTempWarningUserMessage(data.Message, false); }
        }
        else {
          functions.SetSelector(record, "false");
        }
      }
    });
  };

  functions.SetSelectionCounter = function (counter) {
    var elements = functions.SelectionCounter();
    if (counter != 0) {
      elements.each(function () {
        $(this).html(counter);
        $(this).addClass("ais-menu-item-tip-border");
        functions.EnableSelectionMenuItem();
      });
    }
    else {
      elements.each(function () {
        $(this).html("");
        $(this).removeClass("ais-menu-item-tip-border");
        functions.DisableSelectionMenuItem();
      });
    }
  };

  functions.GetSelectionCounter = function () {
    var counterHtml = functions.SelectionCounter().html();

    if (counterHtml) {
      return parseInt(counterHtml);
    }
    else { return 0; }
  };
  return functions;
}();;
if (typeof AIS === 'undefined') AIS = {};
AIS.LoadDynamics = (function () {
  var init = function (id, placeholderId, parameters) {
    $(document).ready(function () {
      processLoads();
    });
  }

  function processLoads() {
    var elements = document.getElementsByClassName("loadDynamic");
    for (var i = 0; i < elements.length; i++) {
      var elem = elements[i];
      var loaderText = elem.getAttribute("data-loaderText");
      elem.innerHTML = "<div class=\"ui active inverted dimmer\"><div class=\"ui mini text loader\">" + loaderText + "</div></div>";
      var id = elem.getAttribute("data-id");
      var placeHolderId = elem.getAttribute("data-placeholder");
      var parameter = elem.getAttribute("data-parameters");
      //  alert(id + " " + placeHolderId + " " + parameter);
      makeRequest(id, placeHolderId, parameter);
    }
  }

  function makeRequest(id, placeholderId, parameter) {
    $.ajax({
      url: "/LoadDynamic/" + id + "/" + placeholderId + "/",
      type: "POST",
      accept: "application/json",
      contentType: "application/json",
      data: JSON.stringify({ queryString: parameter }),
      async: true,
      success: successCallback,
      error: errorCallback
    });
  }

  function successCallback(data) {
    var elem = document.querySelector('[data-placeholder="' + data.PlaceholderId + '"]');
    var groupname = elem.getAttribute("data-groupname");
    if (elem === "null") return;
    if (data.Code === 200) {
      elem.innerHTML = data.Message;
      if (groupname === null) return;
      var groupShow = elem.getElementsByClassName("show-label");
      if (groupShow.length > 0) {
        groupShow[0].insertAdjacentText("beforeend", groupname);
      }
      var groupHide = elem.getElementsByClassName("hide-label");
      if (groupHide.length > 0) {
        groupHide[0].insertAdjacentText("beforeend", groupname);
      }
    } else {
      console.log(data.Message);
      elem.innerHTML = "";
    }

  }

  function errorCallback(error) {
    // alert(error);
  }

  return {
    Init: init
  }
})();

AIS.LoadDynamics.Init();;
if (typeof (AIS) !== "object") { var AIS = new Object(); }

AIS.PopupAutoCompleteScan = function () {
  var localStorageAccess = false;
  var spinner, typingTimer, autocompleteTag, scanTag, scanDom, useSpans, url, database, siDatabase, enteredValueInFilterBox, popupmethod, cache, inputfield;
  var dialogElement = $("#popupAutoSuggestScan");
  var content = $(".popup-content");
  var doneTypingInterval = 200;
  var response = {};
  var isLoading = false;
  var language = "";

  $("#popupLookupValue").keyup(function () {
    enteredValueInFilterBox = $(this).val();

    var key = popupmethod;
    key += popupmethod === "autocomplete" ? autocompleteTag : scanTag;
    key += enteredValueInFilterBox;

    // If value is already in cache, then dont apply typing interval
    if (localStorageAccess) {
      if (localStorage[key]) {
        clearTimeout(typingTimer);
        makeApiCallOrReturnCacheData();
      }
    }

    clearTimeout(typingTimer);
    typingTimer = setTimeout(function () {
      makeApiCallOrReturnCacheData();
    }, doneTypingInterval);
  });

  function parseData(adlibJSON) {
    if (adlibJSON.recordList === undefined)
      return;
    /* temp API backward compatibility fix: old webapi misses record node in json, later/current versions have a record node */
    var recordList = adlibJSON.recordList.record === undefined ? adlibJSON.recordList : adlibJSON.recordList.record;
    if (recordList === undefined) {
      return;
    }
    if (recordList === 0) {
      return;
    }
    loopOverRecords(recordList);
    setPaging(adlibJSON.diagnostic);
  };

  function showLoading() {
    isLoading = true;
    spinner.show();
  }

  function hideLoading() {
    isLoading = false;
    spinner.hide();
  }

  function setPaging(diagnostics) {
    $("#currentPage").text(response.CurrentPage);
    if (response.HasNext) {
      var b = $("#popupNextButton");//.show();
      b.addClass('enabled');
      b.removeClass('disabled');
    } else {
      b = $("#popupNextButton");//.hide();
      b.removeClass('enabled');
      b.addClass('disabled');
    }
    if (response.HasPrevious) {
      b = $("#popupPreviousButton");//.show();
      b.addClass('enabled');
      b.removeClass('disabled');
    } else {
      b = $("#popupPreviousButton");
      b.removeClass('enabled');
      b.addClass('disabled');
      b.off('click');
      //$("#popupPreviousButton").hide();
    }
  }

  function loopOverRecords(recordList) {
    var ul = document.createElement("ul");
    for (var i = 0; i < recordList.length; i++) {
      var item = recordList[i];
      if (popupmethod === "autocomplete") {
        ul.appendChild(createLiElement(item.term[0]));
      } else {
        ul.appendChild(createLiElement(item.TE[0]));
      }

    }
    content.append(ul);
  };

  function createLiElement(item) {
    var li = document.createElement("li");
    li.setAttribute("onclick", "AIS.PopupAutoCompleteScan.Click(this);");
    if (item.spans === undefined) {
      li.innerHTML = item;
      li.setAttribute("cleartext", item);
      li.setAttribute("title", item);
    } else {
      addCombinedSpansToLi(item.spans, li);
    }
    return li;
  };

  function addCombinedSpansToLi(spans, liElement, clearText) {
    var clearText = "";
    for (var i = 0; i < spans.length; i++) {
      var span = spans[i];
      clearText += span.text;

      // attributes can contain: 1 = bold
      if (span.attributes === undefined) {
        liElement.innerHTML += span.text;
      } else {
        if (span.attributes === 1) {
          var spanelement = document.createElement("span");
          spanelement.innerHTML += span.text;
          spanelement.className = "span";
          liElement.appendChild(spanelement);
        }
      }
    }
    liElement.setAttribute("cleartext", clearText);
  }

  function createAutoCompleteData() {
    return {
      url: url,
      dataType: "json",
      data: {
        database: database,
        autocompletetag: autocompleteTag,
        language: language,
        usespans: useSpans,
        enteredvalue: enteredValueInFilterBox,
        popupmethod: popupmethod
      },
      success: successCallback,
      error: errorCallback
    }
  };

  function createScanData() {
    if (enteredValueInFilterBox === '') {
      enteredValueInFilterBox = inputfield.val();//el.parent().children(".webapi").val();
    }
    return {
      url: url,
      dataType: "json",
      data: {
        database: database,
        scantag: scanTag,
        scandom: scanDom,
        language: language,
        usespans: useSpans,
        enteredvalue: enteredValueInFilterBox,
        popupmethod: popupmethod
      },
      success: successCallback,
      error: errorCallback
    }
  };

  function makeApiCallOrReturnCacheData() {
    showLoading();

    // Get from cache, else get from api
    var data = getFromCache(enteredValueInFilterBox);
    if (data !== null) {
      successCallback(JSON.parse(data));
    }
    else if (popupmethod === "autocomplete") {
      var data = createAutoCompleteData();
      $.ajax(data);
    } else if (scanTag === undefined || scanTag === "") {
      content.text("Error: No scantag defined, and autocomplete is not defined or turned off in formsettings.");
      hideLoading();
    } else {
      var data = createScanData();
      $.ajax(data);
    }
  };

  function goNextOrPrevious(type) {
    showLoading();

    var minOrPlus = 0;
    if (type === "next") {
      minOrPlus = 1;
    } else {
      minOrPlus = -1;
    }
    var data = getFromCache(enteredValueInFilterBox, response.CurrentPage + minOrPlus);
    if (data !== null) {
      successCallback(JSON.parse(data));
      return;
    }

    if (popupmethod == "autocomplete") {
      data = createAutoCompleteData();
    } else {
      data = createScanData();
    }

    if (type === "next") {
      data.data.startfrom = response.NextStartFrom;
    } else {
      data.data.startfrom = response.PreviousStartFrom;
    }

    $.ajax(data);
  }

  function getFromCache(value, page) {
    var key = popupmethod;
    key += popupmethod === "autocomplete" ? autocompleteTag : scanTag;
    key += value || "";
    key += page || response.CurrentPage;
    key += language;
    if (!localStorageAccess) {
      return cache[key];
    }
    return localStorage.getItem(key);
  }
  function successCallback(dto) {
    response = dto;
    var val = dto.Value === null ? "" : dto.Value;
    if (enteredValueInFilterBox !== val) {
      writeCache(dto);
      return;
    }
    content.text("");
    if (dto.AdlibJson.adlibJSON !== undefined) {
      writeCache(dto);
      parseData(dto.AdlibJson.adlibJSON);
    }
    hideLoading();
  };

  function writeCache(dto) {
    if (localStorageAccess) {
      var cacheDate = localStorage.getItem("cachedate");
      var dateNow = new Date();
      if (cacheDate === null) {
        cacheDate = new Date();
        localStorage.setItem("cachedate", cacheDate);
      } else if ((dateNow.getTime() - new Date(cacheDate).getTime()) > 1800000) { // 30 Minutes cache | 1000 = 1 sec | 60000 = 1 minute | 3600000 = 1 hour
        localStorage.clear();
      }
      var tag = popupmethod === "autocomplete" ? autocompleteTag : scanTag;
      var val = dto.Value === null ? "" : dto.Value;
      var key = dto.PopupMethod + tag + val + response.CurrentPage + language;
      var storageItem = localStorage.getItem(key);

      try {
        localStorage.setItem(key, JSON.stringify(dto));
      }
      catch (error) {
        localStorage.clear();
      }

    } else {
      cache[data.Value] = data;
    }
  }

  function errorCallback(error) {
    hideLoading();
  }

  function init(element) {
    response = {};
    dialogElement.dialog({ autoOpen: false });
    spinner = $("#popupAutoSuggestScan  .popup-spinner").show();
    document.getElementById("popupLookupValue").value = "";
    autocompleteTag = element.siblings("input[autocompletetag]").attr('autocompletetag');
    scanTag = element.siblings("input[scantag]").attr('scantag');
    scanDom = element.siblings("input[scantag]").attr('scandom');
    //language = $('#ais-search-language').val();
    useSpans = element.siblings("input[usespans]").attr('usespans') === "true";
    url = AIS.Helpers.ResolveUrl("/helper/GetAutoCompleteOrScanValues");
    database = $(".ais-database-choices-script option:selected").val();
    if (database === undefined) database = $("#SourceName").val();
    siDatabase = element.siblings("input[popupmethod]").attr('database');
    if (siDatabase != '') database = siDatabase; 
    enteredValueInFilterBox = "";
    popupmethod = element.siblings("input[popupmethod]").attr('popupmethod');
    cache = {
      startCacheDate: new Date()
    };
    inputfield = element.siblings(".form-input");

    if (typeof (Storage) !== "undefined") {
      localStorageAccess = true;
    }
  };

  function close() {
    dialogElement.dialog("close");
  }

  var click = function (element) {
    inputfield.val(element.getAttribute("cleartext"));
    close();
  };

  var open = function (element, isExpert) {
    response = {};
    var popuptitle = null;
    if (isExpert) {
      popuptitle = element.parent().parent().children(".ais-field-selector-script").children("option:selected").text();
    } else {
      popuptitle = element.parent().parent().children(".form-label").find("a").text();
    }
    init(element);
    content.text("")
    makeApiCallOrReturnCacheData(element);
    $("#popupAutoSuggestScan").dialog({ autoOpen: true, modal: true, title: popuptitle, draggable: false, resizable: false });
  };

  var nextPage = function (event) {
    if (isLoading) return;
    event.preventDefault();
    goNextOrPrevious("next");
  };

  var previousPage = function (event) {
    if (isLoading) return;
    event.preventDefault();
    goNextOrPrevious("previous");
  }

  return {
    Open: open,
    Click: click,
    NextPage: nextPage,
    PreviousPage: previousPage
  }
}();

AIS.PopupLookup = function () {

  var loadHtmlPopup = function (controllerUrl, lookupInput, term, page) {

    // Takes each argument name and value from lookupInput and puts it in the query string
    //var query = $.map(lookupInput, function (v, p) { return p + "=" + v; })
    //  .join("&") + "&term=" + term + "&page=" + page;
    //var query = $.map(lookupInput, function (v, p) { return p + "=" + v; })
    //  .join("&");


    $.ajax({
      type: "get",
      url: AIS.Helpers.ResolveUrl(controllerUrl),
      data: {
        database: lookupInput.database,
        fieldName: lookupInput.fieldName,
        searchType: lookupInput.searchType,
        term: term,
        page: page
      },
      dataType: "json",
      success: function (data) {
        AIS.PopupLookup.Popup().html(data.content);

        AIS.PopupLookup.Popup().dialog({
          modal: true,
          title: AIS.PopupLookup.PopupTitle().val(),
          resizable: false,
          width: 'auto'
        });
        updateButtonsDisplay(controllerUrl, lookupInput);
      }
    });
  };

  var disableButton = function (b) {
    b.removeClass('enabled');
    b.addClass('disabled');
    b.off('click');
  };

  var enableButton = function (b) {
    b.addClass('enabled');
    b.removeClass('disabled');
  };

  var updateButtonsDisplay = function (controllerUrl, lookupInput) {

    disableButton(AIS.PopupLookup.FirstPageNavigationButton());
    disableButton(AIS.PopupLookup.BackNavigationButton());
    disableButton(AIS.PopupLookup.NextNavigationButton());
    disableButton(AIS.PopupLookup.LastPageNavigationButton());

    if (AIS.PopupLookup.Options().length !== 0) {

      AIS.PopupLookup.NoResultsMessage().addClass('ais-not-visible');

      if (AIS.PopupLookup.LastPage() > 1) {
        AIS.PopupLookup.Navigator().show();

        if (AIS.PopupLookup.CurrentPage() !== AIS.PopupLookup.FirstPage()) {

          enableButton(AIS.PopupLookup.FirstPageNavigationButton());
          AIS.PopupLookup.FirstPageNavigationButton().on('click', function () {
            loadHtmlPopup(controllerUrl, lookupInput,
              AIS.PopupLookup.SearchTerm(), AIS.PopupLookup.FirstPage());
          });

          enableButton(AIS.PopupLookup.BackNavigationButton());
          AIS.PopupLookup.BackNavigationButton().on('click', function () {
            loadHtmlPopup(controllerUrl, lookupInput,
              AIS.PopupLookup.SearchTerm(), AIS.PopupLookup.CurrentPage() - 1);
          });

        }

        if (AIS.PopupLookup.CurrentPage() !== AIS.PopupLookup.LastPage()) {

          enableButton(AIS.PopupLookup.NextNavigationButton());
          AIS.PopupLookup.NextNavigationButton().on('click', function () {
            loadHtmlPopup(controllerUrl, lookupInput,
              AIS.PopupLookup.SearchTerm(), AIS.PopupLookup.CurrentPage() + 1);
          });

          enableButton(AIS.PopupLookup.LastPageNavigationButton());
          AIS.PopupLookup.LastPageNavigationButton().on('click', function () {
            loadHtmlPopup(controllerUrl, lookupInput,
              AIS.PopupLookup.SearchTerm(), AIS.PopupLookup.LastPage());
          });
        }
      } else {
        AIS.PopupLookup.Navigator().hide();
      }
    } else {
      AIS.PopupLookup.NoResultsMessage().removeClass('ais-not-visible');
      AIS.PopupLookup.Navigator().hide();
    }
  };

  return {

    Open: function (controllerUrl, lookupInput, fieldId, term, page, callback) {

      // Unbind any previous live events
      AIS.PopupLookup.Options().off('click');
      AIS.PopupLookup.SearchButton().off('click');
      AIS.PopupLookup.FirstPageNavigationButton().off('click');
      AIS.PopupLookup.BackNavigationButton().off('click');
      AIS.PopupLookup.NextNavigationButton().off('click');
      AIS.PopupLookup.LastPageNavigationButton().off('click');
      AIS.PopupLookup.GoToPageNavigationButton().off('click');

      // First page popup
      loadHtmlPopup(controllerUrl, lookupInput, term, AIS.PopupLookup.DefaultPage());

      // Bind live events

      // Lookup value
      AIS.PopupLookup.Options().on('click', function () {
        var selectorExpression = AIS.Helpers.EscapeSelectorExpression(fieldId);
        $('#' + selectorExpression).val($(this).text());

        //execute function sent as parameter
        if (callback !== undefined) callback();

        AIS.PopupLookup.Popup().dialog('close');
      });

      // Search button
      AIS.PopupLookup.SearchButton().on('click', function () {
        loadHtmlPopup(controllerUrl, lookupInput, AIS.PopupLookup.SearchTerm(), AIS.PopupLookup.DefaultPage());
      });

      // Go To Navigation buttons
      AIS.PopupLookup.GoToPageNavigationButton().on('click', function () {
        loadHtmlPopup(controllerUrl, lookupInput, AIS.PopupLookup.SearchTerm(), AIS.PopupLookup.CurrentPage());
      });
    },

    FirstPage: function () { return 1; },

    DefaultPage: function () { return AIS.PopupLookup.FirstPage(); },

    Popup: function () { return $(".ais-popupwrapper-script"); },

    PopupTitle: function () { return $(".ais-popupwrapper-script .popup-lookup-title-value"); },

    Options: function () { return $('.ais-popupwrapper-script .popup-lookup-list-script li a'); },

    NoResultsMessage: function () { return $('.ais-popupwrapper-script .no-results-found-element'); },

    Navigator: function () { return $('.ais-popupwrapper-script .ais-navigator-script'); },

    SearchButton: function () { return $('.ais-popupwrapper-script .ais-popup-lookup-search-script'); },

    FirstPageNavigationButton: function () { return $('.ais-popupwrapper-script .ais-navigator-script .first-page-script'); },

    BackNavigationButton: function () { return $('.ais-popupwrapper-script .ais-navigator-script .prev-page-script'); },

    NextNavigationButton: function () { return $('.ais-popupwrapper-script .ais-navigator-script .next-page-script'); },

    LastPageNavigationButton: function () { return $('.ais-popupwrapper-script .ais-navigator-script .last-page-script'); },

    GoToPageNavigationButton: function () { return $('.ais-popupwrapper-script .ais-navigator-script .goto-page-script'); },

    SearchTerm: function () { return $(".ais-popupwrapper-script .ais-popup-lookup-value").val(); },

    CurrentPage: function () { return parseInt($(".ais-popupwrapper-script .current-page-script").val()); },

    LastPage: function () { return parseInt($(".ais-popupwrapper-script .total-pages-script").text()); }
  }
}();;
AIS = AIS || {};
AIS.WindowManager = function () {
  var loading;
  var isLoading = function() {
    return loading;
  }

  var showResultsLoader = function () {
    loading = true;
    $(document.querySelectorAll(".loader-container")).each(function (index, elem) { $(elem).fadeIn("fast") });
  }

  var hideResultsLoader = function () {
    loading = false;
    $(document.querySelectorAll(".loader-container")).each(function (index, elem) { $(elem).fadeOut("fast") });
  }

  function init() {
    loading = false;
  }
  init();

  return {
    ShowResultsLoader: showResultsLoader,
    HideResultsLoader: hideResultsLoader,
    IsLoading: isLoading
  }
}();;
if (typeof (AIS) !== "object") { var AIS = new Object(); }

AIS.ImageViewer = function () {
  return {

    Open: function (sender) {

      $(document).off("click", AIS.ImageViewer.NextImageButton);
      $(document).off("click", AIS.ImageViewer.PreviousImageButton);

      //bind events to buttons

      AIS.ImageViewer.GetViewerHtml(sender);

      // zooming
      $(document).on("click", AIS.ImageViewer.ZoomInButton, function () {
        var cz = $(AIS.ImageViewer.CurrentZoomMultiplier).val();
        var zm = $(AIS.ImageViewer.ZoomMultiplier).val();
        $(AIS.ImageViewer.CurrentZoomMultiplier).val(parseFloat(cz) + parseFloat(zm) - 1);
        AIS.ImageViewer.UpdateImageURLSize();
      });

      $(document).on("click", AIS.ImageViewer.ZoomOutButton, function () {
        var cz = $(AIS.ImageViewer.CurrentZoomMultiplier).val();
        var zm = $(AIS.ImageViewer.ZoomMultiplier).val();
        $(AIS.ImageViewer.CurrentZoomMultiplier).val(parseFloat(cz) - parseFloat(zm) + 1);
        AIS.ImageViewer.UpdateImageURLSize();
      });

      // listing
      $(document).on("click", AIS.ImageViewer.NextImageButton, function () {
        var currIndex = parseInt($(AIS.ImageViewer.CurrentImageIndex).val());
        if (currIndex + 1 >= AIS.ImageViewer.TotalImages/2) {
          AIS.ImageViewer.SetIndex(0);
        }
        else {
          AIS.ImageViewer.SetIndex(currIndex + 1);
        }

        var imageFilename = ($(AIS.ImageViewer.Filenames)[$(AIS.ImageViewer.CurrentImageIndex).val()]).value;

        AIS.ImageViewer.UpdateImageURLSource(imageFilename);
      });

      $(document).on("click", AIS.ImageViewer.PreviousImageButton, function () {
        var currIndex = $(AIS.ImageViewer.CurrentImageIndex).val();
        if (currIndex <= 0) {
          AIS.ImageViewer.SetIndex(AIS.ImageViewer.TotalImages/2 - 1);
        }
        else {
          AIS.ImageViewer.SetIndex(currIndex - 1);
        }

        var imageFilename = $(AIS.ImageViewer.Filenames)[$(AIS.ImageViewer.CurrentImageIndex).val()].value;

        AIS.ImageViewer.UpdateImageURLSource(imageFilename);
      });

      // printing
      $(document).on("click", AIS.ImageViewer.PrintButton, function () {
        var printContents = $(".ais-image-viewer-image-container").html();
        var newWindow = window.open();
        newWindow.document.open();
        newWindow.document.write(printContents);
        newWindow.document.close(); // necessary for IE >= 10
        newWindow.focus(); // necessary for IE >= 10
        if (newWindow.addEventListener) {// W3C DOM
          newWindow.addEventListener('load', (event) => {
            newWindow.print();
            setTimeout(function () {
              newWindow.close();
            }, 0);
          });
        }
        else if (newWindow.attachEvent) { // IE DOM
          newWindow.attachEvent("onload", function () {
            newWindow.print();
            newWindow.close();
          });
        }
      });
    },

    // loading

    GetViewerHtml: function (sender) {

      var index = $(".ais-detail-image-viewer-script").index(sender);

      var _commentImage = "false";
      var urlSplit = document.URL.split("/");
      var priref = urlSplit[urlSplit.length - 1];
      if ($(sender).hasClass("ais-comment-image")) { _commentImage = "true"; }
      $.ajax({
        type: "get",
        url: AIS.Helpers.ResolveUrl("/helper/GetImageViewer"),
        data: {
          filename: $($(".ais-image-filename-value").get(index)).val(),
          databaseid: $(".ais-database-name").val(),
          imageServer: $(".ais-image-server").val(),
          priref: priref,
          totalimages: $(AIS.ImageViewer.Filenames).length/2,
          commentImage: _commentImage
        },
        dataType: "html",
        success: function (html) {
          $(AIS.ImageViewer.Popup).html(html);
          $(AIS.ImageViewer.Popup).dialog({
            title: "",
            width: 'auto',
            modal: true,
            position: { my: "center", at: "top", of: window },
            resizable: false,
            open: function () {
              jQuery('.ui-widget-overlay').bind('click', function () {
                jQuery(AIS.ImageViewer.Popup).dialog('close');
              })
            }
          });
          var left = $(".page").position().left;
          var top = $(".page").position().top;
          $(".ui-dialog").css({
            top: top + 'px',
            left: left + 'px'
          });
          AIS.ImageViewer.SetIndex(index);
        }
      });
    },

    // url update functions

    UpdateImageURLSize: function () {
      var s = $(AIS.ImageViewer.DefaultSize).val();
      var z = $(AIS.ImageViewer.CurrentZoomMultiplier).val();
      if (z < 0.5) {
        z = 0.5;
        $(AIS.ImageViewer.CurrentZoomMultiplier).val(0.5);
      }
      if (z > 3) {
        z = 3;
        $(AIS.ImageViewer.CurrentZoomMultiplier).val(3);
      }
      var size = Math.floor(s * z);
      if (size < $(AIS.ImageViewer.MinSize).val()) {
        size = $(AIS.ImageViewer.MinSize).val();
      }
      var urlSplit = document.URL.split("/");
      var priref = urlSplit[urlSplit.length - 1];
      $.ajax({
        type: "get",
        url: AIS.Helpers.ResolveUrl("/helper/GetImageURL"),
        async: false,
        data: {
          filename: AIS.ImageViewer.CurrentFilename(),
          databaseid: $(".ais-database-name").val(),
          imageServer: $(".ais-image-server").val(),
          priref: priref,
          size: size,
          commentImage: AIS.ImageViewer.CommentImageFlag
        },
        dataType: "html",
        success: function (url) {
          $(AIS.ImageViewer.Image).attr("src", url + "&imageformat=jpg");
          $(AIS.ImageViewer.CurrentSize).val(size);
        }
      });
    },

    UpdateImageURLSource: function (filename) {
      var urlSplit = document.URL.split("/");
      var priref = urlSplit[urlSplit.length - 1];
      $.ajax({
        type: "get",
        url: AIS.Helpers.ResolveUrl("/helper/GetImageURL"),
        data: {
          filename: filename,
          databaseid: $(".ais-database-name").val(),
          imageServer: $(".ais-image-server").val(),
          priref: priref,
          size: $(AIS.ImageViewer.CurrentSize).val()
        },
        dataType: "html",
        success: function (url) {
          $(AIS.ImageViewer.Image).attr("src", url + "&imageformat=jpg");
        }
      });
    },

    // accessors

    // buttons
    NextImageButton: ".ais-images-listing-script .ais-next-image-script",
    PreviousImageButton: ".ais-images-listing-script .ais-prev-image-script",
    ZoomInButton: ".ais-image-viewer-zoom .ais-zoom-in-script",
    ZoomOutButton: ".ais-image-viewer-zoom .ais-zoom-out-script",
    PrintButton: "#ais-image-viewer-print .ais-print-script",
    // variables
    CurrentSize: ".ais-image-viewer-controls .ais-current-size-value",
    CurrentImageIndex: ".ais-images-listing-script .ais-current-image-index-value",
    CurrentFilename: function () {
      var index = $(AIS.ImageViewer.CurrentImageIndex).val();
      return $($(".ais-image-filename-value").get(index)).val();
    },

    SetIndex: function (index) {
      $(AIS.ImageViewer.CurrentImageIndex).val(index);
      $("span.ais-current-image-number-element").html(index + 1);
    },

    // inputs and settings
    DefaultSize: ".ais-image-viewer-controls .ais-default-size-value",
    MinSize: ".ais-image-viewer-controls .ais-image-viewer-zoom .ais-min-size-value",
    ZoomMultiplier: ".ais-image-viewer-controls .ais-zoom-multiplier-value",
    CurrentZoomMultiplier: ".ais-image-viewer-controls .ais-current-zoom-multiplier-value",
    CommentImageFlag: ".ais-image-viewer-controls .ais-image-viewer-zoom .ais-comment-image-flag",
    Filenames: ".ais-image-filename-value",
    TotalImages: $(".ais-image-filename-value").length / 2,

    // objects 
    Image: ".ais-popupwrapper-script .ais-image-viewer-image-container img.ais-image-viewer-image-element",
    Popup: ".ais-popupwrapper-script"

  }

}();
;
if (typeof (AIS) !== "object") { var AIS = new Object(); }

AIS.ProjectRequest = function () {
    var spinner = $(".loadingNamesSpinner");
    var searchBox = $(".participantSearchBox");
    var resultList = $(".participantsList.results");
    var existingParticipantsList = $(".participantsList.existing");
    var typingTimer;
    var url = AIS.Helpers.ResolveUrl("/helper/GetSearchResult");
    var participantUrl = AIS.Helpers.ResolveUrl("/activity/");

    function init() {
        searchBox.keyup(searchBoxChanged);
    }

    function searchBoxChanged() {
        clearTimeout(typingTimer);
        typingTimer = setTimeout(function () {
            if (searchBox.val() !== '') {
                startLoadingVisual();
                getParticipantsFromApi();
            } else {
                resultList.empty();
            };
        }, 350);
    }

    function getParticipantsFromApi() {
        var data = {
            url: url,
            dataType: "json",
            traditional: true,
            data: {
                Database: "PeopleWorkflow",
                SearchStatement: "do=staff%20and%20un=*%20and%20name=\"*" + searchBox.val() + "*\"",
                Limit: 1000,
                Fields: "name, priref",
            },
            success: serverSearchResult,
            error: serverSearchError
        };
        $.ajax(data);
    }

    function serverSearchResult(data) {
        resultList.empty();
        if (data.Result != null) {
            for (index in data.Result.record) {
                var item = data.Result.record[index];
                var priref = item.priref;
                var name = item.name[0][0].value;
                addChildToList(resultList, priref, name, "AddParticipant");
            }
        }
        $(".scroll.results").animate({ scrollTop: 0 }, "fast");
        stopLoadingVisual();
    }

    function addChildToList(list, priref, name, action) {
        var positiveOrNegative = "";
        var text = "";
        var icon = "";
        if (action === "AddParticipant") {
            positiveOrNegative = "positive";
            text = "Add";
            icon = "fa fa-plus-circle";
        } else {
            positiveOrNegative = "negative";
            text = "Remove";
            icon = "fa fa-trash-o";
        }
        var activityId = $(".box.search").attr("data-activityid");

        list.append("<li id=" + priref + " class=\"participantsListItem\"><div class=\"left\">" + name + "</div><div class=\"right\"> <a href=\"#\" onclick=\"AIS.ProjectRequest." + action + "(" + activityId + "," + priref + ", '" + name + "')\" class=\"iconbutton " + positiveOrNegative + "\"><i class=\"" + icon + "\" aria-hidden=\"true\"></i>" + text + "</a></div></li>")
    }

    function serverSearchError(error) {
        stopLoadingVisual();
    }

    function startLoadingVisual() {
        spinner.show();
        searchBox.hide();
    }
    function stopLoadingVisual() {
        spinner.hide();
        searchBox.show();
        searchBox.focus();
    }

    var participantsList = [];
    function addParticipant(projectId, personId, name) {
        participantsList.push({ key: personId, value: name });
        resultList.children("#" + personId).find(".fa").removeClass("fa-plus-circle");
        resultList.children("#" + personId).find(".fa").addClass("fa-spinner fa-spin");
        participantApiCall("AddParticipant", projectId, personId);
    }

    function removeParticipant(projectId, personId) {
        existingParticipantsList.children("#" + personId).find(".fa").removeClass("fa-trash-o");
        existingParticipantsList.children("#" + personId).find(".fa").addClass("fa-spinner fa-spin");
        participantApiCall("RemoveParticipant", projectId, personId);
    }

    function participantApiCall(action, projectId, personId) {
        var url = participantUrl + "AddOrRemoveParticipant";
        var data = {
            url: url,
            dataType: "json",
            traditional: true,
            data: {
                ProjectPriref: projectId,
                ParticipantPriref: personId,
                ActionType: action
            },
        };
        if (action === "AddParticipant") {
            data.success = serverAddResult;
            data.error = serverAddError;
        } else {
            data.success = serverRemoveResult;
            data.error = serverRemoveError;
        }
        $.ajax(data);
    }

    function serverAddResult(data) {
        if (!data.ErrorOccured && data.Result.recordList.record.actionSucceeded === 'true') {
            var participantPriref = data.RequestValues.dto.ParticipantPriref;
            var name = getNameFromList(participantPriref);
            addChildToList(existingParticipantsList, participantPriref, name, "RemoveParticipant");
            $(".scroll.existing").animate({ scrollTop: 9999 }, "slow");
        }
        resultList.children("#" + data.RequestValues.dto.ParticipantPriref).find(".fa").removeClass("fa-spinner fa-spin");
        resultList.children("#" + data.RequestValues.dto.ParticipantPriref).find(".fa").addClass("fa-plus-circle");
    }

    function getNameFromList(participantPriref) {
        for (var i = 0; i < participantsList.length; i++) {
            var item = participantsList[i];
            if (item.key === participantPriref) {
                return item.value;
            }
        }
        return undefined;
    }

    function serverRemoveResult(data) {
        if (!data.ErrorOccured && data.Result.recordList.record.actionSucceeded === 'true') {
            existingParticipantsList.children("#" + data.RequestValues.dto.ParticipantPriref).remove();
        }
    }

    function serverAddError(error) {
        console.log(error);
    }

    function serverRemoveError(error) {
        console.log(error);
    }

    var saveButton;
    function updateField(link) {
        saveButton = $(link).children();
        saveVisual(true);
        var fieldvalue = $("#requestDetailsText").val();
        var priref = link.getAttribute("data-priref");
        var fieldname = link.getAttribute("data-fieldname");
        var database = link.getAttribute("data-database");

        updateFieldApiCall(priref, fieldname, fieldvalue, database);
    }

    function updateFieldApiCall(priref, fieldname, fieldvalue, database) {
        var data = {
            url: AIS.Helpers.ResolveUrl("/activity/UpdateField"),
            dataType: "json",
            traditional: true,
            data: {
                Priref: priref,
                Fieldname: fieldname,
                Fieldvalue: fieldvalue,
                Database: database
            },
            success: serverUpdateFieldResult,
            error: serverUpdateFieldError
        }
        $.ajax(data);
    }

    function serverUpdateFieldResult(data) {
        saveVisual(false);
    }

    function serverUpdateFieldError(error) {
        console.log(error);
    }

    function saveVisual(showVisual) {
        if (showVisual) {
            saveButton.removeClass("fa-floppy-o");
            saveButton.addClass("fa-spinner fa-spin");
        } else {
            saveButton.removeClass("fa-spinner fa-spin");
            saveButton.addClass("fa-floppy-o");
        }
    }

    function updateDescriptionField(priref, element) {
        var icon = $(element).children();
        var value = $("#" + priref + "comment").val();
        var data = {
            url: AIS.Helpers.ResolveUrl("/activity/UpdateField"),
            dataType: "json",
            traditional: true,
            data: {
                Priref: priref,
                Fieldname: "comments",
                Fieldvalue: value,
                Database: "workitem"
            },
            beforeSend: function () {
                icon.removeClass("fa-floppy-o");
                icon.addClass("fa-spinner fa-spin");
            },
            success: function (data) {
                if (data.ErrorOccured) {
                    $("#" + priref + "failed").show().delay(2000).fadeOut();
                } else {
                    $("#" + priref + "saved").show().delay(2000).fadeOut();
                }
                icon.removeClass("fa-spinner fa-spin");
                icon.addClass("fa-floppy-o");
            },
            error: function (error) {
                $("#" + priref + "failed").show().delay(2000).fadeOut();
                icon.removeClass("fa-spinner fa-spin");
                icon.addClass("fa-floppy-o");
            }
        }
        $.ajax(data);
    }

    function isValidDate(date) {
        if (date === undefined) {
            return false;
        }
        if (date === null) {
            return false;
        }
        if (date.length !== 10) {
            return false;
        }
        if (date[4] !== "-") {
            return false;
        }
        if (date[7] !== "-") {
            return false;
        }
        var isNumeric = /^[-+]?(\d+|\d+\.\d*|\d*\.\d+)$/;
        //Year
        if (!isNumeric.test(date.substr(0, 3))) {
            return false;
        }

        //Month
        var month = date.substr(5, 2);
        if (!isNumeric.test(month)) return false;
        if (Number(month) > 12) return false;
        if (Number(month) < 1) return false;

        //Day
        var day = date.substr(8, 2);
        if (!isNumeric.test(day)) return false;
        if (Number(day) > 31) return false;
        if (Number(day) < 1) return false;
        return true;
    }

    function updateFields(priref, element) {
        var icon = $(element).children();
        var projectName = $("*[data-fieldname='project.name']").val();
        var description = $("*[data-fieldname='description']").val();
        var patronValue = $("#requestDetailsText").val();
        var dueDate = $("#dueDate").val();

        if (!isValidDate(dueDate)) {
            $("#dueDate").css("background-color", "#bb2222");
            $("#dueDate").css("color", "white");
            return;
        }
        //var selectedState = $("#stateSelection option:selected").val();
        //var selectedStatus = $("#statusSelection option:selected").val();
        var values = [];
        if (projectName !== undefined) {
            values.push({ Key: "project.name", Value: projectName });
        }
        if (description !== undefined) {
            values.push({ Key: "description", Value: description });
        }
        if (patronValue !== undefined) {
            values.push({ Key: "request.by.details", value: patronValue });
        }
        if (dueDate !== undefined) {
            values.push({ Key: "due.date", value: dueDate });
        }
        //if (selectedState !== "") {
        //  values.push({ Key: "state", Value: selectedState, IsGrouped:true });
        //}
        //if (selectedStatus !== "") {
        //  values.push({ Key: "state.status", Value: selectedStatus, IsGrouped:true });
        //}
        var settings = {
            type: "POST",
            url: AIS.Helpers.ResolveUrl("/activity/UpdateMultipleFields"),
            dataType: "json",
            traditional: true,
            data: JSON.stringify({
                Priref: priref,
                Values: values,
                Database: "workflow"
            }),
            beforeSend: function () {
                icon.removeClass("fa-floppy-o");
                icon.addClass("fa-spinner fa-spin");
            },
            success: function (data) {
                if (data.ErrorOccured) {
                    $("#detailsFailed").show().delay(2000).fadeOut();
                } else {
                    $("#activity-title").text(projectName);
                    $("#detailsSaved").show().delay(2000).fadeOut();
                }
                icon.removeClass("fa-spinner fa-spin");
                icon.addClass("fa-floppy-o");
                $("#dueDate").css("background-color", "white");
                $("#dueDate").css("color", "black");
            },
            error: function (error) {
                $("#Detailsfailed").show().delay(2000).fadeOut();
                icon.removeClass("fa-spinner fa-spin");
                icon.addClass("fa-floppy-o");
            }
        }
        $.ajax(settings);
    }

    function openSendEmailDialog() {
        $("#activity-dialog").dialog({ modal: true, draggable: false, resizable: false, width: 425 });
    }

    function sendProjectInformation(element, priref) {
        var email = $("#Email-ToEmail").val();
        var url = AIS.Helpers.ResolveUrl("activity/Email");
        var icon = $(element.children[0]);
        var settings = {
            type: "POST",
            url: url,
            dataType: "json",
            traditional: true,
            data: JSON.stringify({
                Priref: priref,
                ToEmail: email,
                subjectKey: "ActivitySubject"
            }),
            beforeSend: function () {
                icon.removeClass("fa-envelope-o");
                icon.addClass("fa-spinner fa-spin");
            },
            success: function (data) {
                if (data) {
                    icon.removeClass("fa-spinner fa-spin");
                    icon.addClass("fa-envelope-o");
                    $("#Email-ToEmail").val("");
                    $("#activity-dialog").dialog('close');
                } else {
                    $("#Detailsfailed").show().delay(2000).fadeOut();
                    icon.removeClass("fa-spinner fa-spin");
                    icon.addClass("fa-envelope-o");
                }
            },
            error: function () {
                $("#Detailsfailed").show().delay(2000).fadeOut();
                icon.removeClass("fa-spinner fa-spin");
                icon.addClass("fa-envelope-o");
            }
        }
        $.ajax(settings);
    }

    init();
    return {
        AddParticipant: addParticipant,
        RemoveParticipant: removeParticipant,
        UpdateField: updateField,
        UpdateDescriptionField: updateDescriptionField,
        UpdateFields: updateFields,
        OpenSendEmailDialog: openSendEmailDialog,
        SendProjectInformation: sendProjectInformation
    };
}();;
var AIS = AIS || {};
AIS.Facets = function () {

  var facetSelect = function (event, elem, group, index) {
    var url = AIS.Helpers.ResolveUrl("results/facetSelect/" + group + "/" + index);
    $("html, #ais-master").animate({ scrollTop: 0 }, 300);
    makeApiCall(url);
  }

  var facetDeselect = function (event, elem, index) {
    var url = AIS.Helpers.ResolveUrl("results/facetDeselect/" + index);
    makeApiCall(url);
  }

  var toggleGroupMore = function (element) {
    //var oht = 0;
    var showItem = parseInt($(element).attr("show"),10);
    var showNextItem = parseInt(showItem, 10) + parseInt(10, 10);
    var allItems = $(element).siblings(".facet-table").children(".facet-row").length;
    showNextItem = allItems < showNextItem ? allItems : showNextItem;
    if (showItem === 0) {
      $(element).siblings(".facet-table").children(".facet-row").slice(4).slideToggle("fast");
      $(element).attr("show", 4);
      $(element).children(".collapseMoreIcon").toggle();
      $(element).children(".expandMoreIcon").toggle();
      $('html, body').animate({
        scrollTop: $("body").offset().top
      }, 1000);
    }
    else {
      $(element).siblings(".facet-table").children(".facet-row").slice(showItem, showNextItem).slideToggle("fast");

      $(element).attr("show", showNextItem);
      if (showNextItem >= parseInt(allItems,10)) {
        $(element).children(".collapseMoreIcon").toggle();
        $(element).children(".expandMoreIcon").toggle();
        $(element).attr("show", 0);
      }
      //for (var i = showItem; i <= showNextItem; i++) {
      //  oht += $(element).siblings(".facet-table").children(".facet-row").eq(i).height();
      //}

      //$('html, body').animate({
      //  scrollTop: '+='+oht+'px'
      //}, 1000);

      var ele = $(element).parents(".facet-group").next();
      $(ele)[0].scrollIntoView({ aligntotop:false, behavior: "smooth", block: "end" });

    }
    //$(element).parent().find(".facet-table .facet-row").show();
    //$(element).siblings(".facet-table").slideToggle("fast");
  }

  var toggleGroup = function (element) {
    $(element).children(".collapseIcon").toggleClass("display-none");
    $(element).children(".expandIcon").toggleClass("display-inline");
    $(element).siblings(".facet-group-content").slideToggle("fast");
  }

  function doLogic(data) {
    if (data.hasOwnProperty("Error")) {
      console.log("error");
    } else {
      $("#ais-main-content").html(data.RecordsHtml);
      $("#facet-search-container").html(data.FacetHtml);
      $('.ais-brief-gallery').imagesLoaded(function () {
        for (var i = 0; i < 5; i++) {
          var maxHeight = 0;
          var maxImageHeight = 0;
          $(".ais-brief-gallery>ul>li").slice(i * 3, i * 3 + 3).each(function () {
            var thisH = $(this).find(".content").height() + 12;
            var thisImageH = $(this).find(".logo").height() + 12;
            if (thisH > maxHeight) { maxHeight = thisH; }
            if (thisImageH > maxImageHeight) { maxImageHeight = thisImageH; }
          });
          $(".ais-brief-gallery>ul>li").slice(i * 3, i * 3 + 3).each(function () {  //.content
            var thisH = $(this).find(".content").height() + 12;
            $(this).find(".content").css("padding-bottom", maxHeight - thisH);
            $(this).find(".content").attr("max", maxHeight);
            $(this).find(".content").attr("h", thisH);
          });
          $(".ais-brief-gallery>ul>li").slice(i * 3, i * 3 + 3).each(function () {//.logo
            var thisH = $(this).find(".logo").height() + 12;
            $(this).find(".logo").css("padding-top", maxImageHeight - thisH);
            $(this).find(".logo").attr("max", maxImageHeight);
            $(this).find(".logo").attr("h", thisH);
          });
        }
      });
    }
  }

  function makeApiCall(url) {
    if (AIS.WindowManager.IsLoading()) return;
    AIS.WindowManager.ShowResultsLoader();
    $.ajax({
      url: url,
      beforeSend: function () {

      },
      complete: function () {
        AIS.WindowManager.HideResultsLoader();
      },
      success: function (data) {
        doLogic(data);
      },
      error: function (error) {

      }
    });
  }


  return {
    FacetSelect: facetSelect,
    FacetDeselect: facetDeselect,
    ToggleGroup: toggleGroup,
    ToggleGroupMore: toggleGroupMore
  }
}();;
/*!
 * jQuery Form Plugin
 * version: 2.83 (11-JUL-2011)
 * @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($) {

/*
	Usage Note:
	-----------
	Do not use both ajaxSubmit and ajaxForm on the same form.  These
	functions are intended to be exclusive.  Use ajaxSubmit if you want
	to bind your own submit handler to the form.  For example,

	$(document).ready(function() {
		$('#myForm').bind('submit', function(e) {
			e.preventDefault(); // <-- important
			$(this).ajaxSubmit({
				target: '#output'
			});
		});
	});

	Use ajaxForm when you want the plugin to manage all the event binding
	for you.  For example,

	$(document).ready(function() {
		$('#myForm').ajaxForm({
			target: '#output'
		});
	});

	When using ajaxForm, the ajaxSubmit function will be invoked for you
	at the appropriate time.
*/

/**
 * ajaxSubmit() provides a mechanism for immediately submitting
 * an HTML form using AJAX.
 */
$.fn.ajaxSubmit = function(options) {
	// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
	if (!this.length) {
		log('ajaxSubmit: skipping submit process - no element selected');
		return this;
	}
	
	var method, action, url, $form = this;

	if (typeof options === 'function')
	{
		options = { success: options };
	}

	method = this.attr('method');
	action = this.attr('action');
	url = (typeof action === 'string') ? $.trim(action) : '';
	url = url || window.location.href || '';
	if (url) {
		// clean url (don't include hash vaue)
		url = (url.match(/^([^#]+)/)||[])[1];
	}

	options = $.extend(true, {
		url:  url,
		success: $.ajaxSettings.success,
		type: method || 'GET',
		iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
	}, options);

	// hook for manipulating the form data before it is extracted;
	// convenient for use with rich editors like tinyMCE or FCKEditor
	var veto = {};
	this.trigger('form-pre-serialize', [this, options, veto]);
	if (veto.veto) {
		log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
		return this;
	}

	// provide opportunity to alter form data before it is serialized
	if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
		log('ajaxSubmit: submit aborted via beforeSerialize callback');
		return this;
	}

	var n,v,a = this.formToArray(options.semantic);
	if (options.data) {
		options.extraData = options.data;
		for (n in options.data) {
			if(options.data[n] instanceof Array) {
				for (var k in options.data[n]) {
					a.push( { name: n, value: options.data[n][k] } );
				}
			}
			else {
				v = options.data[n];
				v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
				a.push( { name: n, value: v } );
			}
		}
	}

	// give pre-submit callback an opportunity to abort the submit
	if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
		log('ajaxSubmit: submit aborted via beforeSubmit callback');
		return this;
	}

	// fire vetoable 'validate' event
	this.trigger('form-submit-validate', [a, this, options, veto]);
	if (veto.veto) {
		log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
		return this;
	}

	var q = $.param(a);

	if (options.type.toUpperCase() === 'GET') {
		options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
		options.data = null;  // data is null for 'get'
	}
	else {
		options.data = q; // data is the query string for 'post'
	}

	var callbacks = [];
	if (options.resetForm) {
		callbacks.push(function() { $form.resetForm(); });
	}
	if (options.clearForm) {
		callbacks.push(function() { $form.clearForm(); });
	}

	// perform a load on the target only if dataType is not provided
	if (!options.dataType && options.target) {
		var oldSuccess = options.success || function(){};
		callbacks.push(function(data) {
			var fn = options.replaceTarget ? 'replaceWith' : 'html';
			$(options.target)[fn](data).each(oldSuccess, arguments);
		});
	}
	else if (options.success) {
		callbacks.push(options.success);
	}

	options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
		var context = options.context || options;   // jQuery 1.4+ supports scope context 
		for (var i=0, max=callbacks.length; i < max; i++) {
			callbacks[i].apply(context, [data, status, xhr || $form, $form]);
		}
	};

	// are there files to upload?
	var fileInputs = $('input:file', this).length > 0;
	var mp = 'multipart/form-data';
	var multipart = ($form.attr('enctype') === mp || $form.attr('encoding') === mp);

	// options.iframe allows user to force iframe mode
	// 06-NOV-09: now defaulting to iframe mode if file input is detected
   if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
	   // hack to fix Safari hang (thanks to Tim Molendijk for this)
	   // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
	   if (options.closeKeepAlive) {
		   $.get(options.closeKeepAlive, function() { fileUpload(a); });
		}
	   else {
		   fileUpload(a);
		}
   }
   else {
		// IE7 massage (see issue 57)
		if ($.browser.msie && method === 'get') { 
			var ieMeth = $form[0].getAttribute('method');
			if (typeof ieMeth === 'string')
				options.type = ieMeth;
		}
		$.ajax(options);
   }

	// fire 'notify' event
	this.trigger('form-submit-notify', [this, options]);
	return this;


	// private function for handling file uploads (hat tip to YAHOO!)
	function fileUpload(a) {
		var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
        var useProp = !!$.fn.prop;

        if (a) {
        	// ensure that every serialized input is still enabled
          	for (i=0; i < a.length; i++) {
                el = $(form[a[i].name]);
                el[ useProp ? 'prop' : 'attr' ]('disabled', false);
          	}
        }

		if ($(':input[name=submit],:input[id=submit]', form).length) {
			// if there is an input with a name or id of 'submit' then we won't be
			// able to invoke the submit fn on the form (at least not x-browser)
			alert('Error: Form elements must not have name or id of "submit".');
			return;
		}
		
		s = $.extend(true, {}, $.ajaxSettings, options);
		s.context = s.context || s;
		id = 'jqFormIO' + (new Date().getTime());
		if (s.iframeTarget) {
			$io = $(s.iframeTarget);
			n = $io.attr('name');
			if (n === null)
			 	$io.attr('name', id);
			else
				id = n;
		}
		else {
			$io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
			$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
		}
		io = $io[0];


		xhr = { // mock object
			aborted: 0,
			responseText: null,
			responseXML: null,
			status: 0,
			statusText: 'n/a',
			getAllResponseHeaders: function() {},
			getResponseHeader: function() {},
			setRequestHeader: function() {},
			abort: function(status) {
				var e = (status === 'timeout' ? 'timeout' : 'aborted');
				log('aborting upload... ' + e);
				this.aborted = 1;
				$io.attr('src', s.iframeSrc); // abort op in progress
				xhr.error = e;
				s.error && s.error.call(s.context, xhr, e, status);
				g && $.event.trigger("ajaxError", [xhr, s, e]);
				s.complete && s.complete.call(s.context, xhr, e);
			}
		};

		g = s.global;
		// trigger ajax global events so that activity/block indicators work like normal
		if (g && ! $.active++) {
			$.event.trigger("ajaxStart");
		}
		if (g) {
			$.event.trigger("ajaxSend", [xhr, s]);
		}

		if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
			if (s.global) {
				$.active--;
			}
			return;
		}
		if (xhr.aborted) {
			return;
		}

		// add submitting element to data if we know it
		sub = form.clk;
		if (sub) {
			n = sub.name;
			if (n && !sub.disabled) {
				s.extraData = s.extraData || {};
				s.extraData[n] = sub.value;
				if (sub.type === "image") {
					s.extraData[n+'.x'] = form.clk_x;
					s.extraData[n+'.y'] = form.clk_y;
				}
			}
		}
		
		var CLIENT_TIMEOUT_ABORT = 1;
		var SERVER_ABORT = 2;

		function getDoc(frame) {
			var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
			return doc;
		}
		
		// take a breath so that pending repaints get some cpu time before the upload starts
		function doSubmit() {
			// make sure form attrs are set
			var t = $form.attr('target'), a = $form.attr('action');

			// update form attrs in IE friendly way
			form.setAttribute('target',id);
			if (!method) {
				form.setAttribute('method', 'POST');
			}
			if (a !== s.url) {
				form.setAttribute('action', s.url);
			}

			// ie borks in some cases when setting encoding
			if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
				$form.attr({
					encoding: 'multipart/form-data',
					enctype:  'multipart/form-data'
				});
			}

			// support timout
			if (s.timeout) {
				timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
			}
			
			// look for server aborts
			function checkState() {
				try {
					var state = getDoc(io).readyState;
					log('state = ' + state);
					if (state.toLowerCase() === 'uninitialized')
						setTimeout(checkState,50);
				}
				catch(e) {
					log('Server abort: ' , e, ' (', e.name, ')');
					cb(SERVER_ABORT);
					timeoutHandle && clearTimeout(timeoutHandle);
					timeoutHandle = undefined;
				}
			}

			// add "extra" data to form if provided in options
			var extraInputs = [];
			try {
				if (s.extraData) {
					for (var n in s.extraData) {
						extraInputs.push(
							$('<input type="hidden" name="'+n+'" />').attr('value',s.extraData[n])
								.appendTo(form)[0]);
					}
				}

				if (!s.iframeTarget) {
					// add iframe to doc and submit the form
					$io.appendTo('body');
	                io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
				}
				setTimeout(checkState,15);
				form.submit();
			}
			finally {
				// reset attrs and remove "extra" input elements
				form.setAttribute('action',a);
				if(t) {
					form.setAttribute('target', t);
				} else {
					$form.removeAttr('target');
				}
				$(extraInputs).remove();
			}
		}

		if (s.forceSync) {
			doSubmit();
		}
		else {
			setTimeout(doSubmit, 10); // this lets dom updates render
		}

		var data, doc, domCheckCount = 50, callbackProcessed;

		function cb(e) {
			if (xhr.aborted || callbackProcessed) {
				return;
			}
			try {
				doc = getDoc(io);
			}
			catch(ex) {
				log('cannot access response document: ', ex);
				e = SERVER_ABORT;
			}
			if (e === CLIENT_TIMEOUT_ABORT && xhr) {
				xhr.abort('timeout');
				return;
			}
			else if (e === SERVER_ABORT && xhr) {
				xhr.abort('server abort');
				return;
			}

			if (!doc || doc.location.href === s.iframeSrc) {
				// response not received yet
				if (!timedOut)
					return;
			}
            io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);

			var status = 'success', errMsg;
			try {
				if (timedOut) {
					throw 'timeout';
				}

				var isXml = s.dataType === 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
				log('isXml='+isXml);
				if (!isXml && window.opera && (doc.body === null || doc.body.innerHTML === '')) {
					if (--domCheckCount) {
						// in some browsers (Opera) the iframe DOM is not always traversable when
						// the onload callback fires, so we loop a bit to accommodate
						log('requeing onLoad callback, DOM not available');
						setTimeout(cb, 250);
						return;
					}
					// let this fall through because server response could be an empty document
					//log('Could not access iframe DOM after mutiple tries.');
					//throw 'DOMException: not available';
				}

				//log('response detected');
                var docRoot = doc.body ? doc.body : doc.documentElement;
                xhr.responseText = docRoot ? docRoot.innerHTML : null;
				xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
				if (isXml)
					s.dataType = 'xml';
				xhr.getResponseHeader = function(header){
					var headers = {'content-type': s.dataType};
					return headers[header];
				};
                // support for XHR 'status' & 'statusText' emulation :
                if (docRoot) {
                    xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
                    xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
                }

				var dt = s.dataType || '';
				var scr = /(json|script|text)/.test(dt.toLowerCase());
				if (scr || s.textarea) {
					// see if user embedded response in textarea
					var ta = doc.getElementsByTagName('textarea')[0];
					if (ta) {
						xhr.responseText = ta.value;
                        // support for XHR 'status' & 'statusText' emulation :
                        xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
                        xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
					}
					else if (scr) {
						// account for browsers injecting pre around json response
						var pre = doc.getElementsByTagName('pre')[0];
						var b = doc.getElementsByTagName('body')[0];
						if (pre) {
							xhr.responseText = pre.textContent ? pre.textContent : pre.innerHTML;
						}
						else if (b) {
							xhr.responseText = b.innerHTML;
						}
					}
				}
				else if (s.dataType === 'xml' && !xhr.responseXML && xhr.responseText !== null) {
					xhr.responseXML = toXml(xhr.responseText);
				}

                try {
                    data = httpData(xhr, s.dataType, s);
                }
                catch (e) {
                    status = 'parsererror';
                    xhr.error = errMsg = (e || status);
                }
			}
			catch (e) {
				log('error caught: ',e);
				status = 'error';
                xhr.error = errMsg = (e || status);
			}

			if (xhr.aborted) {
				log('upload aborted');
				status = null;
			}

            if (xhr.status) { // we've set xhr.status
                status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
            }

			// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
			if (status === 'success') {
				s.success && s.success.call(s.context, data, 'success', xhr);
				g && $.event.trigger("ajaxSuccess", [xhr, s]);
			}
            else if (status) {
				if (errMsg === undefined)
					errMsg = xhr.statusText;
				s.error && s.error.call(s.context, xhr, status, errMsg);
				g && $.event.trigger("ajaxError", [xhr, s, errMsg]);
            }

			g && $.event.trigger("ajaxComplete", [xhr, s]);

			if (g && ! --$.active) {
				$.event.trigger("ajaxStop");
			}

			s.complete && s.complete.call(s.context, xhr, status);

			callbackProcessed = true;
			if (s.timeout)
				clearTimeout(timeoutHandle);

			// clean up
			setTimeout(function() {
				if (!s.iframeTarget)
					$io.remove();
				xhr.responseXML = null;
			}, 100);
		}

		var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
			if (window.ActiveXObject) {
				doc = new ActiveXObject('Microsoft.XMLDOM');
				doc.async = 'false';
				doc.loadXML(s);
			}
			else {
				doc = (new DOMParser()).parseFromString(s, 'text/xml');
			}
			return (doc && doc.documentElement && doc.documentElement.nodeName !== 'parsererror') ? doc : null;
		};
		var parseJSON = $.parseJSON || function(s) {
			return window['eval']('(' + s + ')');
		};

		var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4

			var ct = xhr.getResponseHeader('content-type') || '',
				xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
				data = xml ? xhr.responseXML : xhr.responseText;

			if (xml && data.documentElement.nodeName === 'parsererror') {
				$.error && $.error('parsererror');
			}
			if (s && s.dataFilter) {
				data = s.dataFilter(data, type);
			}
			if (typeof data === 'string') {
				if (type === 'json' || !type && ct.indexOf('json') >= 0) {
					data = parseJSON(data);
				} else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
					$.globalEval(data);
				}
			}
			return data;
		};
	}
};

/**
 * ajaxForm() provides a mechanism for fully automating form submission.
 *
 * The advantages of using this method instead of ajaxSubmit() are:
 *
 * 1: This method will include coordinates for <input type="image" /> elements (if the element
 *	is used to submit the form).
 * 2. This method will include the submit element's name/value data (for the element that was
 *	used to submit the form).
 * 3. This method binds the submit() method to the form for you.
 *
 * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
 * passes the options argument along after properly binding events for submit elements and
 * the form itself.
 */
$.fn.ajaxForm = function(options) {
	// in jQuery 1.3+ we can fix mistakes with the ready state
	if (this.length === 0) {
		var o = { s: this.selector, c: this.context };
		if (!$.isReady && o.s) {
			log('DOM not ready, queuing ajaxForm');
			$(function() {
				$(o.s,o.c).ajaxForm(options);
			});
			return this;
		}
		// is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
		log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
		return this;
	}

	return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
		if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
			e.preventDefault();
			$(this).ajaxSubmit(options);
		}
	}).bind('click.form-plugin', function(e) {
		var target = e.target;
		var $el = $(target);
		if (!($el.is(":submit,input:image"))) {
			// is this a child element of the submit el?  (ex: a span within a button)
			var t = $el.closest(':submit');
			if (t.length === 0) {
				return;
			}
			target = t[0];
		}
		var form = this;
		form.clk = target;
		if (target.type === 'image') {
			if (e.offsetX !== undefined) {
				form.clk_x = e.offsetX;
				form.clk_y = e.offsetY;
			} else if (typeof $.fn.offset === 'function') { // try to use dimensions plugin
				var offset = $el.offset();
				form.clk_x = e.pageX - offset.left;
				form.clk_y = e.pageY - offset.top;
			} else {
				form.clk_x = e.pageX - target.offsetLeft;
				form.clk_y = e.pageY - target.offsetTop;
			}
		}
		// clear form vars
		setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
	});
};

// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function() {
	return this.unbind('submit.form-plugin click.form-plugin');
};

/**
 * formToArray() gathers form element data into an array of objects that can
 * be passed to any of the following ajax functions: $.get, $.post, or load.
 * Each object in the array has both a 'name' and 'value' property.  An example of
 * an array for a simple login form might be:
 *
 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
 *
 * It is this array that is passed to pre-submit callback functions provided to the
 * ajaxSubmit() and ajaxForm() methods.
 */
$.fn.formToArray = function(semantic) {
	var a = [];
	if (this.length === 0) {
		return a;
	}

	var form = this[0];
	var els = semantic ? form.getElementsByTagName('*') : form.elements;
	if (!els) {
		return a;
	}

	var i,j,n,v,el,max,jmax;
	for(i=0, max=els.length; i < max; i++) {
		el = els[i];
		n = el.name;
		if (!n) {
			continue;
		}

		if (semantic && form.clk && el.type === "image") {
			// handle image inputs on the fly when semantic === true
			if(!el.disabled && form.clk === el) {
				a.push({name: n, value: $(el).val()});
				a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
			}
			continue;
		}

		v = $.fieldValue(el, true);
		if (v && v.constructor === Array) {
			for(j=0, jmax=v.length; j < jmax; j++) {
				a.push({name: n, value: v[j]});
			}
		}
		else if (v !== null && typeof v !== 'undefined') {
			a.push({name: n, value: v});
		}
	}

	if (!semantic && form.clk) {
		// input type=='image' are not found in elements array! handle it here
		var $input = $(form.clk), input = $input[0];
		n = input.name;
		if (n && !input.disabled && input.type === 'image') {
			a.push({name: n, value: $input.val()});
			a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
		}
	}
	return a;
};

/**
 * Serializes form data into a 'submittable' string. This method will return a string
 * in the format: name1=value1&amp;name2=value2
 */
$.fn.formSerialize = function(semantic) {
	//hand off to jQuery.param for proper encoding
	return $.param(this.formToArray(semantic));
};

/**
 * Serializes all field elements in the jQuery object into a query string.
 * This method will return a string in the format: name1=value1&amp;name2=value2
 */
$.fn.fieldSerialize = function(successful) {
	var a = [];
	this.each(function() {
		var n = this.name;
		if (!n) {
			return;
		}
		var v = $.fieldValue(this, successful);
		if (v && v.constructor === Array) {
			for (var i=0,max=v.length; i < max; i++) {
				a.push({name: n, value: v[i]});
			}
		}
		else if (v !== null && typeof v !== 'undefined') {
			a.push({name: this.name, value: v});
		}
	});
	//hand off to jQuery.param for proper encoding
	return $.param(a);
};

/**
 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
 *
 *  <form><fieldset>
 *	  <input name="A" type="text" />
 *	  <input name="A" type="text" />
 *	  <input name="B" type="checkbox" value="B1" />
 *	  <input name="B" type="checkbox" value="B2"/>
 *	  <input name="C" type="radio" value="C1" />
 *	  <input name="C" type="radio" value="C2" />
 *  </fieldset></form>
 *
 *  var v = $(':text').fieldValue();
 *  // if no values are entered into the text inputs
 *  v === ['','']
 *  // if values entered into the text inputs are 'foo' and 'bar'
 *  v === ['foo','bar']
 *
 *  var v = $(':checkbox').fieldValue();
 *  // if neither checkbox is checked
 *  v === undefined
 *  // if both checkboxes are checked
 *  v === ['B1', 'B2']
 *
 *  var v = $(':radio').fieldValue();
 *  // if neither radio is checked
 *  v === undefined
 *  // if first radio is checked
 *  v === ['C1']
 *
 * The successful argument controls whether or not the field element must be 'successful'
 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
 * The default value of the successful argument is true.  If this value is false the value(s)
 * for each element is returned.
 *
 * Note: This method *always* returns an array.  If no valid value can be determined the
 *	   array will be empty, otherwise it will contain one or more values.
 */
$.fn.fieldValue = function(successful) {
	for (var val=[], i=0, max=this.length; i < max; i++) {
		var el = this[i];
		var v = $.fieldValue(el, successful);
		if (v === null || typeof v === 'undefined' || (v.constructor === Array && !v.length)) {
			continue;
		}
		v.constructor === Array ? $.merge(val, v) : val.push(v);
	}
	return val;
};

/**
 * Returns the value of the field element.
 */
$.fieldValue = function(el, successful) {
	var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
	if (successful === undefined) {
		successful = true;
	}

	if (successful && (!n || el.disabled || t === 'reset' || t === 'button' ||
		(t === 'checkbox' || t === 'radio') && !el.checked ||
		(t === 'submit' || t === 'image') && el.form && el.form.clk !== el ||
		tag === 'select' && el.selectedIndex === -1)) {
			return null;
	}

	if (tag === 'select') {
		var index = el.selectedIndex;
		if (index < 0) {
			return null;
		}
		var a = [], ops = el.options;
		var one = (t === 'select-one');
		var max = (one ? index+1 : ops.length);
		for(var i=(one ? index : 0); i < max; i++) {
			var op = ops[i];
			if (op.selected) {
				var v = op.value;
				if (!v) { // extra pain for IE...
					v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
				}
				if (one) {
					return v;
				}
				a.push(v);
			}
		}
		return a;
	}
	return $(el).val();
};

/**
 * Clears the form data.  Takes the following actions on the form's input fields:
 *  - input text fields will have their 'value' property set to the empty string
 *  - select elements will have their 'selectedIndex' property set to -1
 *  - checkbox and radio inputs will have their 'checked' property set to false
 *  - inputs of type submit, button, reset, and hidden will *not* be effected
 *  - button elements will *not* be effected
 */
$.fn.clearForm = function() {
	return this.each(function() {
		$('input,select,textarea', this).clearFields();
	});
};

/**
 * Clears the selected form elements.
 */
$.fn.clearFields = $.fn.clearInputs = function() {
	var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
	return this.each(function() {
		var t = this.type, tag = this.tagName.toLowerCase();
		if (re.test(t) || tag === 'textarea') {
			this.value = '';
		}
		else if (t === 'checkbox' || t === 'radio') {
			this.checked = false;
		}
		else if (tag === 'select') {
			this.selectedIndex = -1;
		}
	});
};

/**
 * Resets the form data.  Causes all form elements to be reset to their original value.
 */
$.fn.resetForm = function() {
	return this.each(function() {
		// guard against an input with the name of 'reset'
		// note that IE reports the reset function as an 'object'
		if (typeof this.reset === 'function' || (typeof this.reset === 'object' && !this.reset.nodeType)) {
			this.reset();
		}
	});
};

/**
 * Enables or disables any matching elements.
 */
$.fn.enable = function(b) {
	if (b === undefined) {
		b = true;
	}
	return this.each(function() {
		this.disabled = !b;
	});
};

/**
 * Checks/unchecks any matching checkboxes or radio buttons and
 * selects/deselects and matching option elements.
 */
$.fn.selected = function(select) {
	if (select === undefined) {
		select = true;
	}
	return this.each(function() {
		var t = this.type;
		if (t === 'checkbox' || t === 'radio') {
			this.checked = select;
		}
		else if (this.tagName.toLowerCase() === 'option') {
			var $sel = $(this).parent('select');
			if (select && $sel[0] && $sel[0].type === 'select-one') {
				// deselect all other options
				$sel.find('option').selected(false);
			}
			this.selected = select;
		}
	});
};

// helper fn for console logging
function log() {
	var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
	if (window.console && window.console.log) {
		window.console.log(msg);
	}
	else if (window.opera && window.opera.postError) {
		window.opera.postError(msg);
	}
};

})(jQuery);
;
