/* Minification failed. Returning unminified contents.
(5660,9-13): run-time error JS1300: Strict-mode does not allow assignment to undefined variables: ssId
 */
/*! jQuery v1.11.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m="1.11.0",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(l.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:k&&!k.call("\ufeff\xa0")?function(a){return null==a?"":k.call(a)}:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||n.guid++,e):void 0},now:function(){return+new Date},support:l}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=gb(function(a){return m.appendChild(a).id=s,!e.getElementsByName||!e.getElementsByName(s).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==A&&n){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){var c=typeof a.getAttributeNode!==A&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==A?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==A&&n?b.getElementsByClassName(a):void 0},p=[],o=[],(c.qsa=Y.test(e.querySelectorAll))&&(gb(function(a){a.innerHTML="<select t=''><option selected=''></option></select>",a.querySelectorAll("[t^='']").length&&o.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||o.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll(":checked").length||o.push(":checked")}),gb(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&o.push("name"+K+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||o.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),o.push(",.*:")})),(c.matchesSelector=Y.test(q=m.webkitMatchesSelector||m.mozMatchesSelector||m.oMatchesSelector||m.msMatchesSelector))&&gb(function(a){c.disconnectedMatch=q.call(a,"div"),q.call(a,"[s!='']:x"),p.push("!=",O)}),o=o.length&&new RegExp(o.join("|")),p=p.length&&new RegExp(p.join("|")),b=Y.test(m.compareDocumentPosition),r=b||Y.test(m.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},z=b?function(a,b){if(a===b)return j=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===t&&r(t,a)?-1:b===e||b.ownerDocument===t&&r(t,b)?1:i?I.call(i,a)-I.call(i,b):0:4&d?-1:1)}:function(a,b){if(a===b)return j=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],k=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:i?I.call(i,a)-I.call(i,b):0;if(f===g)return ib(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)k.unshift(c);while(h[d]===k[d])d++;return d?ib(h[d],k[d]):h[d]===t?-1:k[d]===t?1:0},e):l},db.matches=function(a,b){return db(a,null,null,b)},db.matchesSelector=function(a,b){if((a.ownerDocument||a)!==l&&k(a),b=b.replace(S,"='$1']"),!(!c.matchesSelector||!n||p&&p.test(b)||o&&o.test(b)))try{var d=q.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return db(b,l,null,[a]).length>0},db.contains=function(a,b){return(a.ownerDocument||a)!==l&&k(a),r(a,b)},db.attr=function(a,b){(a.ownerDocument||a)!==l&&k(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!n):void 0;return void 0!==f?f:c.attributes||!n?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},db.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},db.uniqueSort=function(a){var b,d=[],e=0,f=0;if(j=!c.detectDuplicates,i=!c.sortStable&&a.slice(0),a.sort(z),j){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return i=null,a},e=db.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=db.selectors={cacheLength:50,createPseudo:fb,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ab,bb),a[3]=(a[4]||a[5]||"").replace(ab,bb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||db.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&db.error(a[0]),a},PSEUDO:function(a){var b,c=!a[5]&&a[2];return V.CHILD.test(a[0])?null:(a[3]&&void 0!==a[4]?a[2]=a[4]:c&&T.test(c)&&(b=ob(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ab,bb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=w[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&w(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==A&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=db.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),t=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&t){k=q[s]||(q[s]={}),j=k[a]||[],n=j[0]===u&&j[1],m=j[0]===u&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[u,n,m];break}}else if(t&&(j=(b[s]||(b[s]={}))[a])&&j[0]===u)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(t&&((l[s]||(l[s]={}))[a]=[u,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||db.error("unsupported pseudo: "+a);return e[s]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?fb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:fb(function(a){var b=[],c=[],d=g(a.replace(P,"$1"));return d[s]?fb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:fb(function(a){return function(b){return db(a,b).length>0}}),contains:fb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:fb(function(a){return U.test(a||"")||db.error("unsupported lang: "+a),a=a.replace(ab,bb).toLowerCase(),function(b){var c;do if(c=n?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===m},focus:function(a){return a===l.activeElement&&(!l.hasFocus||l.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:lb(function(){return[0]}),last:lb(function(a,b){return[b-1]}),eq:lb(function(a,b,c){return[0>c?c+b:c]}),even:lb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:lb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:lb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:lb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=jb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=kb(b);function nb(){}nb.prototype=d.filters=d.pseudos,d.setFilters=new nb;function ob(a,b){var c,e,f,g,h,i,j,k=x[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=Q.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?db.error(a):x(a,i).slice(0)}function pb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function qb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=v++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[u,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[s]||(b[s]={}),(h=i[d])&&h[0]===u&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function rb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function sb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function tb(a,b,c,d,e,f){return d&&!d[s]&&(d=tb(d)),e&&!e[s]&&(e=tb(e,f)),fb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||wb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:sb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=sb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=sb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ub(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],i=g||d.relative[" "],j=g?1:0,k=qb(function(a){return a===b},i,!0),l=qb(function(a){return I.call(b,a)>-1},i,!0),m=[function(a,c,d){return!g&&(d||c!==h)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>j;j++)if(c=d.relative[a[j].type])m=[qb(rb(m),c)];else{if(c=d.filter[a[j].type].apply(null,a[j].matches),c[s]){for(e=++j;f>e;e++)if(d.relative[a[e].type])break;return tb(j>1&&rb(m),j>1&&pb(a.slice(0,j-1).concat({value:" "===a[j-2].type?"*":""})).replace(P,"$1"),c,e>j&&ub(a.slice(j,e)),f>e&&ub(a=a.slice(e)),f>e&&pb(a))}m.push(c)}return rb(m)}function vb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,i,j,k){var m,n,o,p=0,q="0",r=f&&[],s=[],t=h,v=f||e&&d.find.TAG("*",k),w=u+=null==t?1:Math.random()||.1,x=v.length;for(k&&(h=g!==l&&g);q!==x&&null!=(m=v[q]);q++){if(e&&m){n=0;while(o=a[n++])if(o(m,g,i)){j.push(m);break}k&&(u=w)}c&&((m=!o&&m)&&p--,f&&r.push(m))}if(p+=q,c&&q!==p){n=0;while(o=b[n++])o(r,s,g,i);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=E.call(j));s=sb(s)}G.apply(j,s),k&&!f&&s.length>0&&p+b.length>1&&db.uniqueSort(j)}return k&&(u=w,h=t),r};return c?fb(f):f}g=db.compile=function(a,b){var c,d=[],e=[],f=y[a+" "];if(!f){b||(b=ob(a)),c=b.length;while(c--)f=ub(b[c]),f[s]?d.push(f):e.push(f);f=y(a,vb(e,d))}return f};function wb(a,b,c){for(var d=0,e=b.length;e>d;d++)db(a,b[d],c);return c}function xb(a,b,e,f){var h,i,j,k,l,m=ob(a);if(!f&&1===m.length){if(i=m[0]=m[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&c.getById&&9===b.nodeType&&n&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(ab,bb),b)||[])[0],!b)return e;a=a.slice(i.shift().value.length)}h=V.needsContext.test(a)?0:i.length;while(h--){if(j=i[h],d.relative[k=j.type])break;if((l=d.find[k])&&(f=l(j.matches[0].replace(ab,bb),$.test(i[0].type)&&mb(b.parentNode)||b))){if(i.splice(h,1),a=f.length&&pb(i),!a)return G.apply(e,f),e;break}}}return g(a,m)(f,b,!n,e,$.test(a)&&mb(b.parentNode)||b),e}return c.sortStable=s.split("").sort(z).join("")===s,c.detectDuplicates=!!j,k(),c.sortDetached=gb(function(a){return 1&a.compareDocumentPosition(l.createElement("div"))}),gb(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||hb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&gb(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||hb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),gb(function(a){return null==a.getAttribute("disabled")})||hb(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),db}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=a.document,A=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,B=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:A.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:z,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=z.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return y.find(a);this.length=1,this[0]=d}return this.context=z,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};B.prototype=n.fn,y=n(z);var C=/^(?:parents|prev(?:Until|All))/,D={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!n(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function E(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return E(a,"nextSibling")},prev:function(a){return E(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(D[a]||(e=n.unique(e)),C.test(a)&&(e=e.reverse())),this.pushStack(e)}});var F=/\S+/g,G={};function H(a){var b=G[a]={};return n.each(a.match(F)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?G[a]||H(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&n.each(arguments,function(a,c){var d;while((d=n.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){if(a===!0?!--n.readyWait:!n.isReady){if(!z.body)return setTimeout(n.ready);n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(z,[n]),n.fn.trigger&&n(z).trigger("ready").off("ready"))}}});function J(){z.addEventListener?(z.removeEventListener("DOMContentLoaded",K,!1),a.removeEventListener("load",K,!1)):(z.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(z.addEventListener||"load"===event.type||"complete"===z.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===z.readyState)setTimeout(n.ready);else if(z.addEventListener)z.addEventListener("DOMContentLoaded",K,!1),a.addEventListener("load",K,!1);else{z.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&z.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!n.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}J(),n.ready()}}()}return I.promise(b)};var L="undefined",M;for(M in n(l))break;l.ownLast="0"!==M,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c=z.getElementsByTagName("body")[0];c&&(a=z.createElement("div"),a.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",b=z.createElement("div"),c.appendChild(a).appendChild(b),typeof b.style.zoom!==L&&(b.style.cssText="border:0;margin:0;width:1px;padding:1px;display:inline;zoom:1",(l.inlineBlockNeedsLayout=3===b.offsetWidth)&&(c.style.zoom=1)),c.removeChild(a),a=b=null)}),function(){var a=z.createElement("div");if(null==l.deleteExpando){l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}}a=null}(),n.acceptData=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(n.acceptData(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f
}}function S(a,b,c){if(n.acceptData(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d]));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=n._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=["Top","Right","Bottom","Left"],V=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},W=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},X=/^(?:checkbox|radio)$/i;!function(){var a=z.createDocumentFragment(),b=z.createElement("div"),c=z.createElement("input");if(b.setAttribute("className","t"),b.innerHTML="  <link/><table></table><a href='/a'>a</a>",l.leadingWhitespace=3===b.firstChild.nodeType,l.tbody=!b.getElementsByTagName("tbody").length,l.htmlSerialize=!!b.getElementsByTagName("link").length,l.html5Clone="<:nav></:nav>"!==z.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,a.appendChild(c),l.appendChecked=c.checked,b.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,a.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){l.noCloneEvent=!1}),b.cloneNode(!0).click()),null==l.deleteExpando){l.deleteExpando=!0;try{delete b.test}catch(d){l.deleteExpando=!1}}a=b=c=null}(),function(){var b,c,d=z.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),l[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var Y=/^(?:input|select|textarea)$/i,Z=/^key/,$=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,ab=/^([^.]*)(?:\.(.+)|)$/;function bb(){return!0}function cb(){return!1}function db(){try{return z.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof n===L||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(F)||[""],h=b.length;while(h--)f=ab.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(F)||[""],j=b.length;while(j--)if(h=ab.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,m,o=[d||z],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||z,3!==d.nodeType&&8!==d.nodeType&&!_.test(p+n.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[n.expando]?b:new n.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),k=n.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!n.isWindow(d)){for(i=k.delegateType||p,_.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||z)&&o.push(l.defaultView||l.parentWindow||a)}m=0;while((h=o[m++])&&!b.isPropagationStopped())b.type=m>1?i:k.bindType||p,f=(n._data(h,"events")||{})[b.type]&&n._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&n.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&n.acceptData(d)&&g&&d[p]&&!n.isWindow(d)){l=d[g],l&&(d[g]=null),n.event.triggered=p;try{d[p]()}catch(r){}n.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((n.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?n(c,this).index(i)>=0:n.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=$.test(e)?this.mouseHooks:Z.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||z),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||z,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==db()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===db()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return n.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=z.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===L&&(a[d]=null),a.detachEvent(d,c))},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&(a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault())?bb:cb):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:cb,isPropagationStopped:cb,isImmediatePropagationStopped:cb,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=bb,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=bb,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),l.submitBubbles||(n.event.special.submit={setup:function(){return n.nodeName(this,"form")?!1:void n.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=n.nodeName(b,"input")||n.nodeName(b,"button")?b.form:void 0;c&&!n._data(c,"submitBubbles")&&(n.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),n._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&n.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return n.nodeName(this,"form")?!1:void n.event.remove(this,"._submit")}}),l.changeBubbles||(n.event.special.change={setup:function(){return Y.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(n.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),n.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),n.event.simulate("change",this,a,!0)})),!1):void n.event.add(this,"beforeactivate._change",function(a){var b=a.target;Y.test(b.nodeName)&&!n._data(b,"changeBubbles")&&(n.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate("change",this.parentNode,a,!0)}),n._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,"._change"),!Y.test(this.nodeName)}}),l.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=n._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=cb;else if(!d)return this;return 1===e&&(g=d,d=function(a){return n().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=cb),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});function eb(a){var b=fb.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var fb="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gb=/ jQuery\d+="(?:null|\d+)"/g,hb=new RegExp("<(?:"+fb+")[\\s/>]","i"),ib=/^\s+/,jb=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,kb=/<([\w:]+)/,lb=/<tbody/i,mb=/<|&#?\w+;/,nb=/<(?:script|style|link)/i,ob=/checked\s*(?:[^=]|=\s*.checked.)/i,pb=/^$|\/(?:java|ecma)script/i,qb=/^true\/(.*)/,rb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,sb={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:l.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},tb=eb(z),ub=tb.appendChild(z.createElement("div"));sb.optgroup=sb.option,sb.tbody=sb.tfoot=sb.colgroup=sb.caption=sb.thead,sb.th=sb.td;function vb(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==L?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==L?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,vb(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function wb(a){X.test(a.type)&&(a.defaultChecked=a.checked)}function xb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function yb(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function zb(a){var b=qb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ab(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}function Bb(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Cb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(yb(b).text=a.text,zb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&X.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}n.extend({clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!hb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ub.innerHTML=a.outerHTML,ub.removeChild(f=ub.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=vb(f),h=vb(a),g=0;null!=(e=h[g]);++g)d[g]&&Cb(e,d[g]);if(b)if(c)for(h=h||vb(a),d=d||vb(f),g=0;null!=(e=h[g]);g++)Bb(e,d[g]);else Bb(a,f);return d=vb(f,"script"),d.length>0&&Ab(d,!i&&vb(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k,m=a.length,o=eb(b),p=[],q=0;m>q;q++)if(f=a[q],f||0===f)if("object"===n.type(f))n.merge(p,f.nodeType?[f]:f);else if(mb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(kb.exec(f)||["",""])[1].toLowerCase(),k=sb[i]||sb._default,h.innerHTML=k[1]+f.replace(jb,"<$1></$2>")+k[2],e=k[0];while(e--)h=h.lastChild;if(!l.leadingWhitespace&&ib.test(f)&&p.push(b.createTextNode(ib.exec(f)[0])),!l.tbody){f="table"!==i||lb.test(f)?"<table>"!==k[1]||lb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)n.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}n.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),l.appendChecked||n.grep(vb(p,"input"),wb),q=0;while(f=p[q++])if((!d||-1===n.inArray(f,d))&&(g=n.contains(f.ownerDocument,f),h=vb(o.appendChild(f),"script"),g&&Ab(h),c)){e=0;while(f=h[e++])pb.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.deleteExpando,m=n.event.special;null!=(d=a[h]);h++)if((b||n.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k?delete d[i]:typeof d.removeAttribute!==L?d.removeAttribute(i):d[i]=null,c.push(f))}}}),n.fn.extend({text:function(a){return W(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||z).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(vb(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&Ab(vb(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(vb(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return W(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(gb,""):void 0;if(!("string"!=typeof a||nb.test(a)||!l.htmlSerialize&&hb.test(a)||!l.leadingWhitespace&&ib.test(a)||sb[(kb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(jb,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(vb(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(vb(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,k=this.length,m=this,o=k-1,p=a[0],q=n.isFunction(p);if(q||k>1&&"string"==typeof p&&!l.checkClone&&ob.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(k&&(i=n.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=n.map(vb(i,"script"),yb),f=g.length;k>j;j++)d=i,j!==o&&(d=n.clone(d,!0,!0),f&&n.merge(g,vb(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,n.map(g,zb),j=0;f>j;j++)d=g[j],pb.test(d.type||"")&&!n._data(d,"globalEval")&&n.contains(h,d)&&(d.src?n._evalUrl&&n._evalUrl(d.src):n.globalEval((d.text||d.textContent||d.innerHTML||"").replace(rb,"")));i=c=null}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],g=n(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Db,Eb={};function Fb(b,c){var d=n(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:n.css(d[0],"display");return d.detach(),e}function Gb(a){var b=z,c=Eb[a];return c||(c=Fb(a,b),"none"!==c&&c||(Db=(Db||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Db[0].contentWindow||Db[0].contentDocument).document,b.write(),b.close(),c=Fb(a,b),Db.detach()),Eb[a]=c),c}!function(){var a,b,c=z.createElement("div"),d="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;padding:0;margin:0;border:0";c.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=c.getElementsByTagName("a")[0],a.style.cssText="float:left;opacity:.5",l.opacity=/^0.5/.test(a.style.opacity),l.cssFloat=!!a.style.cssFloat,c.style.backgroundClip="content-box",c.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===c.style.backgroundClip,a=c=null,l.shrinkWrapBlocks=function(){var a,c,e,f;if(null==b){if(a=z.getElementsByTagName("body")[0],!a)return;f="border:0;width:0;height:0;position:absolute;top:0;left:-9999px",c=z.createElement("div"),e=z.createElement("div"),a.appendChild(c).appendChild(e),b=!1,typeof e.style.zoom!==L&&(e.style.cssText=d+";width:1px;padding:1px;zoom:1",e.innerHTML="<div></div>",e.firstChild.style.width="5px",b=3!==e.offsetWidth),a.removeChild(c),a=c=e=null}return b}}();var Hb=/^margin/,Ib=new RegExp("^("+T+")(?!px)[a-z%]+$","i"),Jb,Kb,Lb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Jb=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)},Kb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Jb(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),Ib.test(g)&&Hb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):z.documentElement.currentStyle&&(Jb=function(a){return a.currentStyle},Kb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Jb(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Ib.test(g)&&!Lb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Mb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h=z.createElement("div"),i="border:0;width:0;height:0;position:absolute;top:0;left:-9999px",j="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;padding:0;margin:0;border:0";h.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",b=h.getElementsByTagName("a")[0],b.style.cssText="float:left;opacity:.5",l.opacity=/^0.5/.test(b.style.opacity),l.cssFloat=!!b.style.cssFloat,h.style.backgroundClip="content-box",h.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===h.style.backgroundClip,b=h=null,n.extend(l,{reliableHiddenOffsets:function(){if(null!=c)return c;var a,b,d,e=z.createElement("div"),f=z.getElementsByTagName("body")[0];if(f)return e.setAttribute("className","t"),e.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=z.createElement("div"),a.style.cssText=i,f.appendChild(a).appendChild(e),e.innerHTML="<table><tr><td></td><td>t</td></tr></table>",b=e.getElementsByTagName("td"),b[0].style.cssText="padding:0;margin:0;border:0;display:none",d=0===b[0].offsetHeight,b[0].style.display="",b[1].style.display="none",c=d&&0===b[0].offsetHeight,f.removeChild(a),e=f=null,c},boxSizing:function(){return null==d&&k(),d},boxSizingReliable:function(){return null==e&&k(),e},pixelPosition:function(){return null==f&&k(),f},reliableMarginRight:function(){var b,c,d,e;if(null==g&&a.getComputedStyle){if(b=z.getElementsByTagName("body")[0],!b)return;c=z.createElement("div"),d=z.createElement("div"),c.style.cssText=i,b.appendChild(c).appendChild(d),e=d.appendChild(z.createElement("div")),e.style.cssText=d.style.cssText=j,e.style.marginRight=e.style.width="0",d.style.width="1px",g=!parseFloat((a.getComputedStyle(e,null)||{}).marginRight),b.removeChild(c)}return g}});function k(){var b,c,h=z.getElementsByTagName("body")[0];h&&(b=z.createElement("div"),c=z.createElement("div"),b.style.cssText=i,h.appendChild(b).appendChild(c),c.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;display:block;padding:1px;border:1px;width:4px;margin-top:1%;top:1%",n.swap(h,null!=h.style.zoom?{zoom:1}:{},function(){d=4===c.offsetWidth}),e=!0,f=!1,g=!0,a.getComputedStyle&&(f="1%"!==(a.getComputedStyle(c,null)||{}).top,e="4px"===(a.getComputedStyle(c,null)||{width:"4px"}).width),h.removeChild(b),c=h=null)}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Nb=/alpha\([^)]*\)/i,Ob=/opacity\s*=\s*([^)]*)/,Pb=/^(none|table(?!-c[ea]).+)/,Qb=new RegExp("^("+T+")(.*)$","i"),Rb=new RegExp("^([+-])=("+T+")","i"),Sb={position:"absolute",visibility:"hidden",display:"block"},Tb={letterSpacing:0,fontWeight:400},Ub=["Webkit","O","Moz","ms"];function Vb(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Ub.length;while(e--)if(b=Ub[e]+c,b in a)return b;return d}function Wb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&V(d)&&(f[g]=n._data(d,"olddisplay",Gb(d.nodeName)))):f[g]||(e=V(d),(c&&"none"!==c||!e)&&n._data(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Xb(a,b,c){var d=Qb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Yb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+U[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+U[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+U[f]+"Width",!0,e))):(g+=n.css(a,"padding"+U[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+U[f]+"Width",!0,e)));return g}function Zb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Jb(a),g=l.boxSizing()&&"border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Kb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Ib.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Yb(a,b,c||(g?"border":"content"),d,f)+"px"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Kb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":l.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;if(b=n.cssProps[h]||(n.cssProps[h]=Vb(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Rb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]="",i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Vb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Kb(a,b,d)),"normal"===f&&b in Tb&&(f=Tb[b]),""===c||c?(e=parseFloat(f),c===!0||n.isNumeric(e)?e||0:f):f}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?0===a.offsetWidth&&Pb.test(n.css(a,"display"))?n.swap(a,Sb,function(){return Zb(a,b,d)}):Zb(a,b,d):void 0},set:function(a,c,d){var e=d&&Jb(a);return Xb(a,c,d?Yb(a,b,d,l.boxSizing()&&"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Ob.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===n.trim(f.replace(Nb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Nb.test(f)?f.replace(Nb,e):f+" "+e)}}),n.cssHooks.marginRight=Mb(l.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},Kb,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+U[d]+b]=f[d]||f[d-2]||f[0];return e}},Hb.test(a)||(n.cssHooks[a+b].set=Xb)}),n.fn.extend({css:function(a,b){return W(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Jb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)
},a,b,arguments.length>1)},show:function(){return Wb(this,!0)},hide:function(){return Wb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){V(this)?n(this).show():n(this).hide()})}});function $b(a,b,c,d,e){return new $b.prototype.init(a,b,c,d,e)}n.Tween=$b,$b.prototype={constructor:$b,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=$b.propHooks[this.prop];return a&&a.get?a.get(this):$b.propHooks._default.get(this)},run:function(a){var b,c=$b.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):$b.propHooks._default.set(this),this}},$b.prototype.init.prototype=$b.prototype,$b.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},$b.propHooks.scrollTop=$b.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=$b.prototype.init,n.fx.step={};var _b,ac,bc=/^(?:toggle|show|hide)$/,cc=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),dc=/queueHooks$/,ec=[jc],fc={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=cc.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&cc.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function gc(){return setTimeout(function(){_b=void 0}),_b=n.now()}function hc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=U[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function ic(a,b,c){for(var d,e=(fc[b]||[]).concat(fc["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function jc(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&V(a),r=n._data(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k=Gb(a.nodeName),"none"===j&&(j=k),"inline"===j&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==k?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],bc.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}if(!n.isEmptyObject(o)){r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=ic(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function kc(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function lc(a,b,c){var d,e,f=0,g=ec.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=_b||gc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:_b||gc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(kc(k,j.opts.specialEasing);g>f;f++)if(d=ec[f].call(j,a,k,j.opts))return d;return n.map(k,ic,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(lc,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],fc[c]=fc[c]||[],fc[c].unshift(b)},prefilter:function(a,b){b?ec.unshift(a):ec.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(V).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=lc(this,n.extend({},a),f);(e||n._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=n._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&dc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=n._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(hc(b,!0),a,d,e)}}),n.each({slideDown:hc("show"),slideUp:hc("hide"),slideToggle:hc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=n.timers,c=0;for(_b=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),_b=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){ac||(ac=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(ac),ac=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e=z.createElement("div");e.setAttribute("className","t"),e.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=e.getElementsByTagName("a")[0],c=z.createElement("select"),d=c.appendChild(z.createElement("option")),b=e.getElementsByTagName("input")[0],a.style.cssText="top:1px",l.getSetAttribute="t"!==e.className,l.style=/top/.test(a.getAttribute("style")),l.hrefNormalized="/a"===a.getAttribute("href"),l.checkOn=!!b.value,l.optSelected=d.selected,l.enctype=!!z.createElement("form").enctype,c.disabled=!0,l.optDisabled=!d.disabled,b=z.createElement("input"),b.setAttribute("value",""),l.input=""===b.getAttribute("value"),b.value="t",b.setAttribute("type","radio"),l.radioValue="t"===b.value,a=b=c=d=e=null}();var mc=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(mc,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.text(a)}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(l.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var nc,oc,pc=n.expr.attrHandle,qc=/^(?:checked|selected)$/i,rc=l.getSetAttribute,sc=l.input;n.fn.extend({attr:function(a,b){return W(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===L?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?oc:nc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(F);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)?sc&&rc||!qc.test(c)?a[d]=!1:a[n.camelCase("default-"+c)]=a[d]=!1:n.attr(a,c,""),a.removeAttribute(rc?c:d)},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),oc={set:function(a,b,c){return b===!1?n.removeAttr(a,c):sc&&rc||!qc.test(c)?a.setAttribute(!rc&&n.propFix[c]||c,c):a[n.camelCase("default-"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=pc[b]||n.find.attr;pc[b]=sc&&rc||!qc.test(b)?function(a,b,d){var e,f;return d||(f=pc[b],pc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,pc[b]=f),e}:function(a,b,c){return c?void 0:a[n.camelCase("default-"+b)]?b.toLowerCase():null}}),sc&&rc||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,"input")?void(a.defaultValue=b):nc&&nc.set(a,b,c)}}),rc||(nc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},pc.id=pc.name=pc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:nc.set},n.attrHooks.contenteditable={set:function(a,b,c){nc.set(a,""===b?!1:b,c)}},n.each(["width","height"],function(a,b){n.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var tc=/^(?:input|select|textarea|button|object)$/i,uc=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return W(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):tc.test(a.nodeName)||uc.test(a.nodeName)&&a.href?0:-1}}}}),l.hrefNormalized||n.each(["href","src"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this}),l.enctype||(n.propFix.enctype="encoding");var vc=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(F)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(vc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(F)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(vc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(F)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===L||"boolean"===c)&&(this.className&&n._data(this,"__className__",this.className),this.className=this.className||a===!1?"":n._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(vc," ").indexOf(b)>=0)return!0;return!1}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var wc=n.now(),xc=/\?/,yc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=n.trim(b+"");return e&&!n.trim(e.replace(yc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():n.error("Invalid JSON: "+b)},n.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var zc,Ac,Bc=/#.*$/,Cc=/([?&])_=[^&]*/,Dc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Ec=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Fc=/^(?:GET|HEAD)$/,Gc=/^\/\//,Hc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Ic={},Jc={},Kc="*/".concat("*");try{Ac=location.href}catch(Lc){Ac=z.createElement("a"),Ac.href="",Ac=Ac.href}zc=Hc.exec(Ac.toLowerCase())||[];function Mc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(F)||[];if(n.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Nc(a,b,c,d){var e={},f=a===Jc;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Oc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Pc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Qc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ac,type:"GET",isLocal:Ec.test(zc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Kc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Oc(Oc(a,n.ajaxSettings),b):Oc(n.ajaxSettings,a)},ajaxPrefilter:Mc(Ic),ajaxTransport:Mc(Jc),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Dc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||Ac)+"").replace(Bc,"").replace(Gc,zc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(F)||[""],null==k.crossDomain&&(c=Hc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===zc[1]&&c[2]===zc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(zc[3]||("http:"===zc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),Nc(Ic,k,b,v),2===t)return v;h=k.global,h&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Fc.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(xc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Cc.test(e)?e.replace(Cc,"$1_="+wc++):e+(xc.test(e)?"&":"?")+"_="+wc++)),k.ifModified&&(n.lastModified[e]&&v.setRequestHeader("If-Modified-Since",n.lastModified[e]),n.etag[e]&&v.setRequestHeader("If-None-Match",n.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Kc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Nc(Jc,k,b,v)){v.readyState=1,h&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Pc(k,v,c)),u=Qc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(n.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var b=n(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!l.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||n.css(a,"display"))},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var Rc=/%20/g,Sc=/\[\]$/,Tc=/\r?\n/g,Uc=/^(?:submit|button|image|reset|file)$/i,Vc=/^(?:input|select|textarea|keygen)/i;function Wc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||Sc.test(a)?d(a,e):Wc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Wc(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Wc(c,a[c],b,e);return d.join("&").replace(Rc,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&Vc.test(this.nodeName)&&!Uc.test(a)&&(this.checked||!X.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(Tc,"\r\n")}}):{name:b.name,value:c.replace(Tc,"\r\n")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&$c()||_c()}:$c;var Xc=0,Yc={},Zc=n.ajaxSettings.xhr();a.ActiveXObject&&n(a).on("unload",function(){for(var a in Yc)Yc[a](void 0,!0)}),l.cors=!!Zc&&"withCredentials"in Zc,Zc=l.ajax=!!Zc,Zc&&n.ajaxTransport(function(a){if(!a.crossDomain||l.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Xc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Yc[g],b=void 0,f.onreadystatechange=n.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Yc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function $c(){try{return new a.XMLHttpRequest}catch(b){}}function _c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=z.head||n("head")[0]||z.documentElement;return{send:function(d,e){b=z.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var ad=[],bd=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=ad.pop()||n.expando+"_"+wc++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(bd.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&bd.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(bd,"$1"+e):b.jsonp!==!1&&(b.url+=(xc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,ad.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||z;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var cd=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&cd)return cd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=a.slice(h,a.length),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&n.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var dd=a.document.documentElement;function ed(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&n.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?(typeof e.getBoundingClientRect!==L&&(d=e.getBoundingClientRect()),c=ed(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||dd;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||dd})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return W(this,function(a,d,e){var f=ed(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Mb(l.pixelPosition,function(a,c){return c?(c=Kb(a,b),Ib.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return W(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var fd=a.jQuery,gd=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=gd),b&&a.jQuery===n&&(a.jQuery=fd),n},typeof b===L&&(a.jQuery=a.$=n),n});
;
/*!
 * jQuery Migrate - v1.2.1 - 2013-05-08
 * https://github.com/jquery/jquery-migrate
 * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors; Licensed MIT
 */
(function( jQuery, window, undefined ) {
// See http://bugs.jquery.com/ticket/13335
// "use strict";


var warnedAbout = {};

// List of warnings already given; public read only
jQuery.migrateWarnings = [];

// Set to true to prevent console output; migrateWarnings still maintained
// jQuery.migrateMute = false;

// Show a message on the console so devs know we're active
if ( !jQuery.migrateMute && window.console && window.console.log ) {
	window.console.log("JQMIGRATE: Logging is active");
}

// Set to false to disable traces that appear with warnings
if ( jQuery.migrateTrace === undefined ) {
	jQuery.migrateTrace = true;
}

// Forget any warnings we've already given; public
jQuery.migrateReset = function() {
	warnedAbout = {};
	jQuery.migrateWarnings.length = 0;
};

function migrateWarn( msg) {
	var console = window.console;
	if ( !warnedAbout[ msg ] ) {
		warnedAbout[ msg ] = true;
		jQuery.migrateWarnings.push( msg );
		if ( console && console.warn && !jQuery.migrateMute ) {
			console.warn( "JQMIGRATE: " + msg );
			if ( jQuery.migrateTrace && console.trace ) {
				console.trace();
			}
		}
	}
}

function migrateWarnProp( obj, prop, value, msg ) {
	if ( Object.defineProperty ) {
		// On ES5 browsers (non-oldIE), warn if the code tries to get prop;
		// allow property to be overwritten in case some other plugin wants it
		try {
			Object.defineProperty( obj, prop, {
				configurable: true,
				enumerable: true,
				get: function() {
					migrateWarn( msg );
					return value;
				},
				set: function( newValue ) {
					migrateWarn( msg );
					value = newValue;
				}
			});
			return;
		} catch( err ) {
			// IE8 is a dope about Object.defineProperty, can't warn there
		}
	}

	// Non-ES5 (or broken) browser; just set the property
	jQuery._definePropertyBroken = true;
	obj[ prop ] = value;
}

if ( document.compatMode === "BackCompat" ) {
	// jQuery has never supported or tested Quirks Mode
	migrateWarn( "jQuery is not compatible with Quirks Mode" );
}


var attrFn = jQuery( "<input/>", { size: 1 } ).attr("size") && jQuery.attrFn,
	oldAttr = jQuery.attr,
	valueAttrGet = jQuery.attrHooks.value && jQuery.attrHooks.value.get ||
		function() { return null; },
	valueAttrSet = jQuery.attrHooks.value && jQuery.attrHooks.value.set ||
		function() { return undefined; },
	rnoType = /^(?:input|button)$/i,
	rnoAttrNodeType = /^[238]$/,
	rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
	ruseDefault = /^(?:checked|selected)$/i;

// jQuery.attrFn
migrateWarnProp( jQuery, "attrFn", attrFn || {}, "jQuery.attrFn is deprecated" );

jQuery.attr = function( elem, name, value, pass ) {
	var lowerName = name.toLowerCase(),
		nType = elem && elem.nodeType;

	if ( pass ) {
		// Since pass is used internally, we only warn for new jQuery
		// versions where there isn't a pass arg in the formal params
		if ( oldAttr.length < 4 ) {
			migrateWarn("jQuery.fn.attr( props, pass ) is deprecated");
		}
		if ( elem && !rnoAttrNodeType.test( nType ) &&
			(attrFn ? name in attrFn : jQuery.isFunction(jQuery.fn[name])) ) {
			return jQuery( elem )[ name ]( value );
		}
	}

	// Warn if user tries to set `type`, since it breaks on IE 6/7/8; by checking
	// for disconnected elements we don't warn on $( "<button>", { type: "button" } ).
	if ( name === "type" && value !== undefined && rnoType.test( elem.nodeName ) && elem.parentNode ) {
		migrateWarn("Can't change the 'type' of an input or button in IE 6/7/8");
	}

	// Restore boolHook for boolean property/attribute synchronization
	if ( !jQuery.attrHooks[ lowerName ] && rboolean.test( lowerName ) ) {
		jQuery.attrHooks[ lowerName ] = {
			get: function( elem, name ) {
				// Align boolean attributes with corresponding properties
				// Fall back to attribute presence where some booleans are not supported
				var attrNode,
					property = jQuery.prop( elem, name );
				return property === true || typeof property !== "boolean" &&
					( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?

					name.toLowerCase() :
					undefined;
			},
			set: function( elem, value, name ) {
				var propName;
				if ( value === false ) {
					// Remove boolean attributes when set to false
					jQuery.removeAttr( elem, name );
				} else {
					// value is true since we know at this point it's type boolean and not false
					// Set boolean attributes to the same name and set the DOM property
					propName = jQuery.propFix[ name ] || name;
					if ( propName in elem ) {
						// Only set the IDL specifically if it already exists on the element
						elem[ propName ] = true;
					}

					elem.setAttribute( name, name.toLowerCase() );
				}
				return name;
			}
		};

		// Warn only for attributes that can remain distinct from their properties post-1.9
		if ( ruseDefault.test( lowerName ) ) {
			migrateWarn( "jQuery.fn.attr('" + lowerName + "') may use property instead of attribute" );
		}
	}

	return oldAttr.call( jQuery, elem, name, value );
};

// attrHooks: value
jQuery.attrHooks.value = {
	get: function( elem, name ) {
		var nodeName = ( elem.nodeName || "" ).toLowerCase();
		if ( nodeName === "button" ) {
			return valueAttrGet.apply( this, arguments );
		}
		if ( nodeName !== "input" && nodeName !== "option" ) {
			migrateWarn("jQuery.fn.attr('value') no longer gets properties");
		}
		return name in elem ?
			elem.value :
			null;
	},
	set: function( elem, value ) {
		var nodeName = ( elem.nodeName || "" ).toLowerCase();
		if ( nodeName === "button" ) {
			return valueAttrSet.apply( this, arguments );
		}
		if ( nodeName !== "input" && nodeName !== "option" ) {
			migrateWarn("jQuery.fn.attr('value', val) no longer sets properties");
		}
		// Does not return so that setAttribute is also used
		elem.value = value;
	}
};


var matched, browser,
	oldInit = jQuery.fn.init,
	oldParseJSON = jQuery.parseJSON,
	// Note: XSS check is done below after string is trimmed
	rquickExpr = /^([^<]*)(<[\w\W]+>)([^>]*)$/;

// $(html) "looks like html" rule change
jQuery.fn.init = function( selector, context, rootjQuery ) {
	var match;

	if ( selector && typeof selector === "string" && !jQuery.isPlainObject( context ) &&
			(match = rquickExpr.exec( jQuery.trim( selector ) )) && match[ 0 ] ) {
		// This is an HTML string according to the "old" rules; is it still?
		if ( selector.charAt( 0 ) !== "<" ) {
			migrateWarn("$(html) HTML strings must start with '<' character");
		}
		if ( match[ 3 ] ) {
			migrateWarn("$(html) HTML text after last tag is ignored");
		}
		// Consistently reject any HTML-like string starting with a hash (#9521)
		// Note that this may break jQuery 1.6.x code that otherwise would work.
		if ( match[ 0 ].charAt( 0 ) === "#" ) {
			migrateWarn("HTML string cannot start with a '#' character");
			jQuery.error("JQMIGRATE: Invalid selector string (XSS)");
		}
		// Now process using loose rules; let pre-1.8 play too
		if ( context && context.context ) {
			// jQuery object as context; parseHTML expects a DOM object
			context = context.context;
		}
		if ( jQuery.parseHTML ) {
			return oldInit.call( this, jQuery.parseHTML( match[ 2 ], context, true ),
					context, rootjQuery );
		}
	}
	return oldInit.apply( this, arguments );
};
jQuery.fn.init.prototype = jQuery.fn;

// Let $.parseJSON(falsy_value) return null
jQuery.parseJSON = function( json ) {
	if ( !json && json !== null ) {
		migrateWarn("jQuery.parseJSON requires a valid JSON string");
		return null;
	}
	return oldParseJSON.apply( this, arguments );
};

jQuery.uaMatch = function( ua ) {
	ua = ua.toLowerCase();

	var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
		/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
		/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
		/(msie) ([\w.]+)/.exec( ua ) ||
		ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
		[];

	return {
		browser: match[ 1 ] || "",
		version: match[ 2 ] || "0"
	};
};

// Don't clobber any existing jQuery.browser in case it's different
if ( !jQuery.browser ) {
	matched = jQuery.uaMatch( navigator.userAgent );
	browser = {};

	if ( matched.browser ) {
		browser[ matched.browser ] = true;
		browser.version = matched.version;
	}

	// Chrome is Webkit, but Webkit is also Safari.
	if ( browser.chrome ) {
		browser.webkit = true;
	} else if ( browser.webkit ) {
		browser.safari = true;
	}

	jQuery.browser = browser;
}

// Warn if the code tries to get jQuery.browser
migrateWarnProp( jQuery, "browser", jQuery.browser, "jQuery.browser is deprecated" );

jQuery.sub = function() {
	function jQuerySub( selector, context ) {
		return new jQuerySub.fn.init( selector, context );
	}
	jQuery.extend( true, jQuerySub, this );
	jQuerySub.superclass = this;
	jQuerySub.fn = jQuerySub.prototype = this();
	jQuerySub.fn.constructor = jQuerySub;
	jQuerySub.sub = this.sub;
	jQuerySub.fn.init = function init( selector, context ) {
		if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
			context = jQuerySub( context );
		}

		return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
	};
	jQuerySub.fn.init.prototype = jQuerySub.fn;
	var rootjQuerySub = jQuerySub(document);
	migrateWarn( "jQuery.sub() is deprecated" );
	return jQuerySub;
};


// Ensure that $.ajax gets the new parseJSON defined in core.js
jQuery.ajaxSetup({
	converters: {
		"text json": jQuery.parseJSON
	}
});


var oldFnData = jQuery.fn.data;

jQuery.fn.data = function( name ) {
	var ret, evt,
		elem = this[0];

	// Handles 1.7 which has this behavior and 1.8 which doesn't
	if ( elem && name === "events" && arguments.length === 1 ) {
		ret = jQuery.data( elem, name );
		evt = jQuery._data( elem, name );
		if ( ( ret === undefined || ret === evt ) && evt !== undefined ) {
			migrateWarn("Use of jQuery.fn.data('events') is deprecated");
			return evt;
		}
	}
	return oldFnData.apply( this, arguments );
};


var rscriptType = /\/(java|ecma)script/i,
	oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack;

jQuery.fn.andSelf = function() {
	migrateWarn("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()");
	return oldSelf.apply( this, arguments );
};

// Since jQuery.clean is used internally on older versions, we only shim if it's missing
if ( !jQuery.clean ) {
	jQuery.clean = function( elems, context, fragment, scripts ) {
		// Set context per 1.8 logic
		context = context || document;
		context = !context.nodeType && context[0] || context;
		context = context.ownerDocument || context;

		migrateWarn("jQuery.clean() is deprecated");

		var i, elem, handleScript, jsTags,
			ret = [];

		jQuery.merge( ret, jQuery.buildFragment( elems, context ).childNodes );

		// Complex logic lifted directly from jQuery 1.8
		if ( fragment ) {
			// Special handling of each script element
			handleScript = function( elem ) {
				// Check if we consider it executable
				if ( !elem.type || rscriptType.test( elem.type ) ) {
					// Detach the script and store it in the scripts array (if provided) or the fragment
					// Return truthy to indicate that it has been handled
					return scripts ?
						scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
						fragment.appendChild( elem );
				}
			};

			for ( i = 0; (elem = ret[i]) != null; i++ ) {
				// Check if we're done after handling an executable script
				if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
					// Append to fragment and handle embedded scripts
					fragment.appendChild( elem );
					if ( typeof elem.getElementsByTagName !== "undefined" ) {
						// handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
						jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );

						// Splice the scripts into ret after their former ancestor and advance our index beyond them
						ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
						i += jsTags.length;
					}
				}
			}
		}

		return ret;
	};
}

var eventAdd = jQuery.event.add,
	eventRemove = jQuery.event.remove,
	eventTrigger = jQuery.event.trigger,
	oldToggle = jQuery.fn.toggle,
	oldLive = jQuery.fn.live,
	oldDie = jQuery.fn.die,
	ajaxEvents = "ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",
	rajaxEvent = new RegExp( "\\b(?:" + ajaxEvents + ")\\b" ),
	rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
	hoverHack = function( events ) {
		if ( typeof( events ) !== "string" || jQuery.event.special.hover ) {
			return events;
		}
		if ( rhoverHack.test( events ) ) {
			migrateWarn("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'");
		}
		return events && events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
	};

// Event props removed in 1.9, put them back if needed; no practical way to warn them
if ( jQuery.event.props && jQuery.event.props[ 0 ] !== "attrChange" ) {
	jQuery.event.props.unshift( "attrChange", "attrName", "relatedNode", "srcElement" );
}

// Undocumented jQuery.event.handle was "deprecated" in jQuery 1.7
if ( jQuery.event.dispatch ) {
	migrateWarnProp( jQuery.event, "handle", jQuery.event.dispatch, "jQuery.event.handle is undocumented and deprecated" );
}

// Support for 'hover' pseudo-event and ajax event warnings
jQuery.event.add = function( elem, types, handler, data, selector ){
	if ( elem !== document && rajaxEvent.test( types ) ) {
		migrateWarn( "AJAX events should be attached to document: " + types );
	}
	eventAdd.call( this, elem, hoverHack( types || "" ), handler, data, selector );
};
jQuery.event.remove = function( elem, types, handler, selector, mappedTypes ){
	eventRemove.call( this, elem, hoverHack( types ) || "", handler, selector, mappedTypes );
};

jQuery.fn.error = function() {
	var args = Array.prototype.slice.call( arguments, 0);
	migrateWarn("jQuery.fn.error() is deprecated");
	args.splice( 0, 0, "error" );
	if ( arguments.length ) {
		return this.bind.apply( this, args );
	}
	// error event should not bubble to window, although it does pre-1.7
	this.triggerHandler.apply( this, args );
	return this;
};

jQuery.fn.toggle = function( fn, fn2 ) {

	// Don't mess with animation or css toggles
	if ( !jQuery.isFunction( fn ) || !jQuery.isFunction( fn2 ) ) {
		return oldToggle.apply( this, arguments );
	}
	migrateWarn("jQuery.fn.toggle(handler, handler...) is deprecated");

	// Save reference to arguments for access in closure
	var args = arguments,
		guid = fn.guid || jQuery.guid++,
		i = 0,
		toggler = function( event ) {
			// Figure out which function to execute
			var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
			jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );

			// Make sure that clicks stop
			event.preventDefault();

			// and execute the function
			return args[ lastToggle ].apply( this, arguments ) || false;
		};

	// link all the functions, so any of them can unbind this click handler
	toggler.guid = guid;
	while ( i < args.length ) {
		args[ i++ ].guid = guid;
	}

	return this.click( toggler );
};

jQuery.fn.live = function( types, data, fn ) {
	migrateWarn("jQuery.fn.live() is deprecated");
	if ( oldLive ) {
		return oldLive.apply( this, arguments );
	}
	jQuery( this.context ).on( types, this.selector, data, fn );
	return this;
};

jQuery.fn.die = function( types, fn ) {
	migrateWarn("jQuery.fn.die() is deprecated");
	if ( oldDie ) {
		return oldDie.apply( this, arguments );
	}
	jQuery( this.context ).off( types, this.selector || "**", fn );
	return this;
};

// Turn global events into document-triggered events
jQuery.event.trigger = function( event, data, elem, onlyHandlers  ){
	if ( !elem && !rajaxEvent.test( event ) ) {
		migrateWarn( "Global events are undocumented and deprecated" );
	}
	return eventTrigger.call( this,  event, data, elem || document, onlyHandlers  );
};
jQuery.each( ajaxEvents.split("|"),
	function( _, name ) {
		jQuery.event.special[ name ] = {
			setup: function() {
				var elem = this;

				// The document needs no shimming; must be !== for oldIE
				if ( elem !== document ) {
					jQuery.event.add( document, name + "." + jQuery.guid, function() {
						jQuery.event.trigger( name, null, elem, true );
					});
					jQuery._data( this, name, jQuery.guid++ );
				}
				return false;
			},
			teardown: function() {
				if ( this !== document ) {
					jQuery.event.remove( document, name + "." + jQuery._data( this, name ) );
				}
				return false;
			}
		};
	}
);


})( jQuery, window );;
/* Modernizr 2.7.1 (Custom Build) | MIT & BSD
 * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderradius-boxshadow-opacity-rgba-textshadow-cssanimations-generatedcontent-cssgradients-csstransforms-csstransforms3d-csstransitions-canvas-canvastext-draganddrop-hashchange-history-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-geolocation-svg-touch-printshiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
 */
;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)u[c[d]]=c[d]in k;return u.list&&(u.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),u}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:e=k.value!=l)),t[a[d]]=!!e;return t}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.7.1",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n=" -webkit- -moz- -o- -ms- ".split(" "),o="Webkit Moz O ms",p=o.split(" "),q=o.toLowerCase().split(" "),r={svg:"http://www.w3.org/2000/svg"},s={},t={},u={},v=[],w=v.slice,x,y=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.backgroundsize=function(){return J("backgroundSize")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b){function l(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function m(){var a=s.elements;return typeof a=="string"?a.split(" "):a}function n(a){var b=j[a[h]];return b||(b={},i++,a[h]=i,j[i]=b),b}function o(a,c,d){c||(c=b);if(k)return c.createElement(a);d||(d=n(c));var g;return d.cache[a]?g=d.cache[a].cloneNode():f.test(a)?g=(d.cache[a]=d.createElem(a)).cloneNode():g=d.createElem(a),g.canHaveChildren&&!e.test(a)&&!g.tagUrn?d.frag.appendChild(g):g}function p(a,c){a||(a=b);if(k)return a.createDocumentFragment();c=c||n(a);var d=c.frag.cloneNode(),e=0,f=m(),g=f.length;for(;e<g;e++)d.createElement(f[e]);return d}function q(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return s.shivMethods?o(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(s,b.frag)}function r(a){a||(a=b);var c=n(a);return s.shivCSS&&!g&&!c.hasCSS&&(c.hasCSS=!!l(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),k||q(a,c),a}function w(a){var b,c=a.getElementsByTagName("*"),d=c.length,e=RegExp("^(?:"+m().join("|")+")$","i"),f=[];while(d--)b=c[d],e.test(b.nodeName)&&f.push(b.applyElement(x(b)));return f}function x(a){var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(u+":"+a.nodeName);while(d--)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function y(a){var b,c=a.split("{"),d=c.length,e=RegExp("(^|[\\s,>+~])("+m().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),f="$1"+u+"\\:$2";while(d--)b=c[d]=c[d].split("}"),b[b.length-1]=b[b.length-1].replace(e,f),c[d]=b.join("}");return c.join("{")}function z(a){var b=a.length;while(b--)a[b].removeNode()}function A(a){function g(){clearTimeout(d._removeSheetTimer),b&&b.removeNode(!0),b=null}var b,c,d=n(a),e=a.namespaces,f=a.parentWindow;return!v||a.printShived?a:(typeof e[u]=="undefined"&&e.add(u),f.attachEvent("onbeforeprint",function(){g();var d,e,f,h=a.styleSheets,i=[],j=h.length,k=Array(j);while(j--)k[j]=h[j];while(f=k.pop())if(!f.disabled&&t.test(f.media)){try{d=f.imports,e=d.length}catch(m){e=0}for(j=0;j<e;j++)k.push(d[j]);try{i.push(f.cssText)}catch(m){}}i=y(i.reverse().join("")),c=w(a),b=l(a,i)}),f.attachEvent("onafterprint",function(){z(c),clearTimeout(d._removeSheetTimer),d._removeSheetTimer=setTimeout(g,500)}),a.printShived=!0,a)}var c="3.7.0",d=a.html5||{},e=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,f=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,g,h="_html5shiv",i=0,j={},k;(function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",g="hidden"in a,k=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){g=!0,k=!0}})();var s={elements:d.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:c,shivCSS:d.shivCSS!==!1,supportsUnknownElements:k,shivMethods:d.shivMethods!==!1,type:"default",shivDocument:r,createElement:o,createDocumentFragment:p};a.html5=s,r(b);var t=/^$|\b(?:all|print)\b/,u="html5shiv",v=!k&&function(){var c=b.documentElement;return typeof b.namespaces!="undefined"&&typeof b.parentWindow!="undefined"&&typeof c.applyElement!="undefined"&&typeof c.removeNode!="undefined"&&typeof a.attachEvent!="undefined"}();s.type+=" print",s.shivPrint=A,A(b)}(this,document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};

//Do not modify this file! Add your own custom tests in modernizr.additionalTests.js;
//Console polyfill so calls like console.log() do not break the page if console object is missing (IE mostly)
/*eslint-disable no-console */
(function (console) {
    'use strict';
    var prop, method;
    var empty = {};
    var dummy = function () { };
    var properties = 'memory'.split(',');
    var methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,table,time,timeEnd,timeStamp,trace,warn').split(',');

    console.log = console.log || dummy;
    console.debug = console.debug || console.log;
    console.warn = console.warn || console.log;
    console.error = console.error || console.warn;
    console.info = console.info || console.warn;
    console.trace = console.trace || function () {
        try {
            throw new Error('Stack trace (not an error)');
        } catch (ex) {
            if (ex.stack) {
                console.log(ex, '\n' + ex.stack);
            }
        }
    };

    while (prop = properties.pop()) {
        console[prop] = console[prop] || empty;
    }
    while (method = methods.pop()) {
        console[method] = console[method] || dummy;
    }
})(window.console = window.console || {});
/*eslint-enable no-console */
;
/*jslint bitwise: true, nomen: true, plusplus: true, white: true */

/*!
* Mediator.js Library v0.9.8
* https://github.com/ajacksified/Mediator.js
*
* Copyright 2013, Jack Lawson
* MIT Licensed (http://www.opensource.org/licenses/mit-license.php)
*
* For more information: http://thejacklawson.com/2011/06/mediators-for-modularized-asynchronous-programming-in-javascript/index.html
* Project on GitHub: https://github.com/ajacksified/Mediator.js
*
* Last update: October 19 2013
*/

(function(global, factory) {
  'use strict';

  if(typeof define === 'function' && define.amd) {
    // AMD
    define('mediator-js', [], function() {
      global.Mediator = factory();
      return global.Mediator;
    });
  } else if (typeof exports !== 'undefined') {
    // Node/CommonJS
    exports.Mediator = factory();
  } else {
    // Browser global
    global.Mediator = factory();
  }
}(this, function() {
  'use strict';

  // We'll generate guids for class instances for easy referencing later on.
  // Subscriber instances will have an id that can be refernced for quick
  // lookups.

  function guidGenerator() {
    var S4 = function() {
       return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
    };

    return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
  }

  // Subscribers are instances of Mediator Channel registrations. We generate
  // an object instance so that it can be updated later on without having to
  // unregister and re-register. Subscribers are constructed with a function
  // to be called, options object, and context.

  function Subscriber(fn, options, context){
    if(!(this instanceof Subscriber)) {
      return new Subscriber(fn, options, context);
    }

    this.id = guidGenerator();
    this.fn = fn;
    this.options = options;
    this.context = context;
    this.channel = null;
  }

  Subscriber.prototype = {
    // Mediator.update on a subscriber instance can update its function,context,
    // or options object. It takes in an object and looks for fn, context, or
    // options keys.

    update: function(options){
      if(options){
        this.fn = options.fn || this.fn;
        this.context = options.context || this.context;
        this.options = options.options || this.options;
        if(this.channel && this.options && this.options.priority !== undefined) {
            this.channel.setPriority(this.id, this.options.priority);
        }
      }
    }
  };


  function Channel(namespace, parent){
    if(!(this instanceof Channel)) {
      return new Channel(namespace);
    }

    this.namespace = namespace || "";
    this._subscribers = [];
    this._channels = {};
    this._parent = parent;
    this.stopped = false;
  }

  // A Mediator channel holds a list of sub-channels and subscribers to be fired
  // when Mediator.publish is called on the Mediator instance. It also contains
  // some methods to manipulate its lists of data; only setPriority and
  // StopPropagation are meant to be used. The other methods should be accessed
  // through the Mediator instance.

  Channel.prototype = {
    addSubscriber: function(fn, options, context){
      var subscriber = new Subscriber(fn, options, context);

      if(options && options.priority !== undefined){
        // Cheap hack to either parse as an int or turn it into 0. Runs faster
        // in many browsers than parseInt with the benefit that it won't
        // return a NaN.
        options.priority = options.priority >> 0;

        if(options.priority < 0){ options.priority = 0; }
        if(options.priority >= this._subscribers.length){ options.priority = this._subscribers.length-1; }

        this._subscribers.splice(options.priority, 0, subscriber);
      }else{
        this._subscribers.push(subscriber);
      }

      subscriber.channel = this;

      return subscriber;
    },

    // The channel instance is passed as an argument to the mediator subscriber,
    // and further subscriber propagation can be called with
    // channel.StopPropagation().
    stopPropagation: function(){
      this.stopped = true;
    },

    getSubscriber: function(identifier){
      var x = 0,
          y = this._subscribers.length;

      for(x, y; x < y; x++){
        if(this._subscribers[x].id === identifier || this._subscribers[x].fn === identifier){
          return this._subscribers[x];
        }
      }
    },

    // Channel.setPriority is useful in updating the order in which Subscribers
    // are called, and takes an identifier (subscriber id or named function) and
    // an array index. It will not search recursively through subchannels.

    setPriority: function(identifier, priority){
      var oldIndex = 0,
          x = 0,
          sub, firstHalf, lastHalf, y;

      for(x = 0, y = this._subscribers.length; x < y; x++){
        if(this._subscribers[x].id === identifier || this._subscribers[x].fn === identifier){
          break;
        }
        oldIndex ++;
      }

      sub = this._subscribers[oldIndex];
      firstHalf = this._subscribers.slice(0, oldIndex);
      lastHalf = this._subscribers.slice(oldIndex+1);

      this._subscribers = firstHalf.concat(lastHalf);
      this._subscribers.splice(priority, 0, sub);
    },

    addChannel: function(channel){
      this._channels[channel] = new Channel((this.namespace ? this.namespace + ':' : '') + channel, this);
    },

    hasChannel: function(channel){
      return this._channels.hasOwnProperty(channel);
    },

    returnChannel: function(channel){
      return this._channels[channel];
    },

    removeSubscriber: function(identifier){
      var x = this._subscribers.length - 1;

      // If we don't pass in an id, we're clearing all
      if(!identifier){
        this._subscribers = [];
        return;
      }

      // Going backwards makes splicing a whole lot easier.
      for(x; x >= 0; x--) {
        if(this._subscribers[x].fn === identifier || this._subscribers[x].id === identifier){
          this._subscribers[x].channel = null;
          this._subscribers.splice(x,1);
        }
      }
    },

    // This will publish arbitrary arguments to a subscriber and then to parent
    // channels.

    publish: function(data){
      var x = 0,
          y = this._subscribers.length,
          shouldCall = false,
          subscriber, l,
          subsBefore,subsAfter;

      // Priority is preserved in the _subscribers index.
      for(x, y; x < y; x++) {
        // By default set the flag to false
        shouldCall = false;
        subscriber = this._subscribers[x];

        if(!this.stopped){
          subsBefore = this._subscribers.length;
          if(subscriber.options !== undefined && typeof subscriber.options.predicate === "function"){
            if(subscriber.options.predicate.apply(subscriber.context, data)){
              // The predicate matches, the callback function should be called
              shouldCall = true;
            }
          }else{
            // There is no predicate to match, the callback should always be called
            shouldCall = true;
          }
        }

        // Check if the callback should be called
        if(shouldCall) {
          // Check if the subscriber has options and if this include the calls options
          if (subscriber.options && subscriber.options.calls !== undefined){
            // Decrease the number of calls left by one
            subscriber.options.calls--;
            // Once the number of calls left reaches zero or less we need to remove the subscriber
            if(subscriber.options.calls < 1){
              this.removeSubscriber(subscriber.id);
            }
          }
          // Now we call the callback, if this in turns publishes to the same channel it will no longer
          // cause the callback to be called as we just removed it as a subscriber
          subscriber.fn.apply(subscriber.context, data);

          subsAfter = this._subscribers.length;
          y = subsAfter;
          if (subsAfter === subsBefore - 1){
            x--;
          }
        }
      }

      if(this._parent){
        this._parent.publish(data);
      }

      this.stopped = false;
    }
  };

  function Mediator() {
    if(!(this instanceof Mediator)) {
      return new Mediator();
    }

    this._channels = new Channel('');
  }

  // A Mediator instance is the interface through which events are registered
  // and removed from publish channels.

  Mediator.prototype = {

    // Returns a channel instance based on namespace, for example
    // application:chat:message:received. If readOnly is true we
    // will refrain from creating non existing channels.

    getChannel: function(namespace, readOnly){
      var channel = this._channels,
          namespaceHierarchy = namespace.split(':'),
          x = 0,
          y = namespaceHierarchy.length;

      if(namespace === ''){
        return channel;
      }

      if(namespaceHierarchy.length > 0){
        for(x, y; x < y; x++){

          if(!channel.hasChannel(namespaceHierarchy[x])){
            if (readOnly) {
              break;
            } else {
              channel.addChannel(namespaceHierarchy[x]);
            }
          }

          channel = channel.returnChannel(namespaceHierarchy[x]);
        }
      }

      return channel;
    },

    // Pass in a channel namespace, function to be called, options, and context
    // to call the function in to Subscribe. It will create a channel if one
    // does not exist. Options can include a predicate to determine if it
    // should be called (based on the data published to it) and a priority
    // index.

    subscribe: function(channelName, fn, options, context){
      var channel = this.getChannel(channelName || "", false);

      options = options || {};
      context = context || {};

      return channel.addSubscriber(fn, options, context);
    },

    // Pass in a channel namespace, function to be called, options, and context
    // to call the function in to Subscribe. It will create a channel if one
    // does not exist. Options can include a predicate to determine if it
    // should be called (based on the data published to it) and a priority
    // index.

    once: function(channelName, fn, options, context){
      options = options || {};
      options.calls = 1;

      return this.subscribe(channelName, fn, options, context);
    },

    // Returns a subscriber for a given subscriber id / named function and
    // channel namespace

    getSubscriber: function(identifier, channelName){
      var channel = this.getChannel(channelName || "", true);
      // We have to check if channel within the hierarchy exists and if it is
      // an exact match for the requested channel
      if (channel.namespace !== channelName) {
        return null;
      }

      return channel.getSubscriber(identifier);
    },

    // Remove a subscriber from a given channel namespace recursively based on
    // a passed-in subscriber id or named function.

    remove: function(channelName, identifier){
      var channel = this.getChannel(channelName || "", true);
      if (channel.namespace !== channelName) {
        return false;
      }

      channel.removeSubscriber(identifier);
    },

    // Publishes arbitrary data to a given channel namespace. Channels are
    // called recursively downwards; a post to application:chat will post to
    // application:chat:receive and application:chat:derp:test:beta:bananas.
    // Called using Mediator.publish("application:chat", [ args ]);

    publish: function(channelName){
      var channel = this.getChannel(channelName || "", true);
      if (channel.namespace !== channelName) {
        return null;
      }

      var args = Array.prototype.slice.call(arguments, 1);

      args.push(channel);

      channel.publish(args);
    }
  };

  // Alias some common names for easy interop
  Mediator.prototype.on = Mediator.prototype.subscribe;
  Mediator.prototype.bind = Mediator.prototype.subscribe;
  Mediator.prototype.emit = Mediator.prototype.publish;
  Mediator.prototype.trigger = Mediator.prototype.publish;
  Mediator.prototype.off = Mediator.prototype.remove;

  // Finally, expose it all.

  Mediator.Channel = Channel;
  Mediator.Subscriber = Subscriber;
  Mediator.version = "0.9.8";

  return Mediator;
}));
;
var KBB = KBB || {};
KBB.Constants = KBB.Constants || {};

KBB.Constants.Regex = (function () {
    'use strict';

    var Regex = {
        Name: /^[A-Za-z].{0,18}[A-Za-z]$/,
        Email: /^[A-Za-z0-9._%+-]+@(?:[A-Za-z0-9-]+\.)+([A-Za-z]{2,4})$/,
        Zip: /^(\d{5}-\d{4})|(\d{5})$/,
        Mileage: /[^0-9]/,
        PhoneNumber: /^\(?(\d{3})\)?[- ]?(\d{3})[- ]?(\d{4})$/
    };

    return {
        Name: Regex.Name,
        Email: Regex.Email,
        Zip: Regex.Zip,
        Mileage: Regex.Mileage,
        PhoneNumber: Regex.PhoneNumber
    };
}());
;
//This file is loaded at the top of the page, so you will not have access to jQuery and the KBB namespaced functions
//Everything you write should be in plain javascript!



var Utils = (function () {
    'use strict';

    // ** BROWSER HISTORY **//
    var pushState = function (data, title, newUrl) {
        if (window.history && window.history.pushState) {
            window.history.pushState(data, title, newUrl);
        }
    };
    // **BROWSER HISTORY END ** //

    var mediator;

    //when domain is added to allowedOrigins with a true flag, it'll be allowed to send messages to Utils
    var allowedOrigins = {
            '//ad.doubleclick.net': true,
            '//s0.2mdn.net': true,
            '//s1.2mdn.net': true
        },


        //message types dictionary - constants for messages coming through post message (usually from the ads)
        messageTypes = {
            api: 'api',
            hideById: 'hideById',
            showAd: 'showAd',
            showById: 'showById',
            resizeAd: 'resizeAd',
            ecoBoost: 'ecoBoost',
            updateBack: 'updateBack'
        },

        //eventTypes - external constants for events originating from Utils
        eventTypes = {
            api: 'api',
            showAd: 'showAd',
            resizeAd: 'resizeAd',
            hideById: 'hideById',
            slotRenderEnded: 'slotRenderEnded'
        },

        //element IDs and functions to call when the element is hidden
        bindings = {},

        //stores elements that have been hidden, and ads/arguments for ads displayed
        history = {
            //element IDs hidden through the Utils.hideById
            hiddenElements: [],

            //ad types shown
            showAd: [],

            //resized ads
            resizeAd: [],

            //api requests
            api: []
        };

    var getDateString = function (expiration, forCookie) {
        if (expiration === 0 || ((typeof expiration === 'string' || expiration instanceof String) && (expiration === '' || expiration.toLowerCase() === 'session'))) {
            if (forCookie) {
                return ''; //Empty expiration means session cookie
            } else {
                //For storage, set expiration date to one hour from now to simulate session
                expiration = new Date();
                expiration.setHours(expiration.getHours() + 1);
            }
        }

        if (!(expiration instanceof Date)) {
            expiration = parseFloat(expiration) || defaultExpirationInDays;
            expiration = new Date(new Date().getTime() + (expiration * 86400000));
        }

        return expiration.toGMTString();
    };

    //Hide the element and trigger an event
    var hideById = function (id) {
        var isHidden = false,
            element = document.getElementById(id);

        if (element) {
            if (element.className) {
                isHidden = element.className.split(' ').indexOf('hidden') >= 0;
            }

            //hide the element if it hasn't been hidden yet
            if (!isHidden) {
                element.className += (element.className === '') ? 'ad hidden' : ' ad hidden'; // forces hidden if ID also has a display attribute
                history.hiddenElements.push(element);

                var func = bindings[element.id];
                if (func) {
                    func.call(element);
                }

            }
        }
    };

    var showById = function (id) {
        var element = document.getElementById(id);
        if (element) {
            var cn = element.className,
                rxp = new RegExp('\\s?\\bad hidden\\b', 'g');
            cn = cn.replace(rxp, '');
            element.className = cn;
        }
    };

    //send ecoBoost data to an iFrame
    // TODO: move this out, Utils.js should not have product-specific code in it
    var ecoBoost = function (event) {
        if (event && KBB.ads && KBB.ads.ecoBoost && KBB.ads.ecoBoost.ecoBoostData) {
            event.source.postMessage(JSON.stringify(KBB.ads.ecoBoost.ecoBoostData), event.origin);
        }
    };

    //change the body color
    // TODO: move this out, Utils.js should not have product or ad-specific code in it
    var updateBack = function (backValue) {
        document.body.style.background = backValue;
    };

    //Listen messages requesting to hide the elements
    //sample javascript line from an iframe: top.postMessage('{"type":"hideById","elementId":"uftier2"}',"*");
    var processMessages = function (event) {
        if (!event || !event.data) {
            return;
        }
        // only process messages from allowed hosts
        var kbbLastIdx = event.origin.toLowerCase().lastIndexOf('kbb.com') || event.origin.toLowerCase().lastIndexOf('na.autotrader.int');
        var isKbbDomain = kbbLastIdx !== -1 && ((kbbLastIdx === event.origin.length - 'kbb.com'.length) || (event.origin.length - 'na.autotrader.int'.length));
        var mediatorChannel = '';

        //for https
        var cleanProtocol = event.origin.replace(location.protocol, '');

        if (allowedOrigins[cleanProtocol] === true || isKbbDomain) {
            try {
                var msg = JSON.parse(event.data);
                switch (msg.type) {
                    case messageTypes.hideById:
                        if (!!msg.elementId) {
                            hideById(msg.elementId);
                            //e.g. hideById:elementId
                            mediatorChannel = eventTypes.hideById + ':' + msg.elementId;
                            mediator.publish(mediatorChannel, msg);
                        }
                        break;
                    case messageTypes.api:
                        mediatorChannel = eventTypes.api + ':' + msg.subType;
                        history.api[mediatorChannel] = event;
                        mediator.publish(mediatorChannel, event);
                        break;
                    case messageTypes.showAd:
                        if (!!msg.adType) {
                            //e.g. showAd:wallpaper, showAd:stm, showAd:categoryOverlay
                            mediatorChannel = eventTypes.showAd + ':' + msg.adType;
                            history.showAd[mediatorChannel] = msg;
                            mediator.publish(mediatorChannel, msg);
                        }
                        break;
                    case messageTypes.resizeAd:
                        if (!!msg.adUniqueId) {
                            //we save the history item as "resizeAd:leaderboard" or "resizeAd:TradeEvaluator"
                            //and fire event "resizeAd"
                            var historyItem = eventTypes.resizeAd + ':' + msg.adUniqueId;
                            history.resizeAd[historyItem] = msg;
                            mediator.publish(eventTypes.resizeAd, msg);
                        }
                        break;
                    case messageTypes.showById:
                        if (!!msg.elementId) {
                            showById(msg.elementId);
                        }
                        break;
                    case messageTypes.ecoBoost:
                        ecoBoost(event);
                        break;
                    case messageTypes.updateBack:
                        updateBack(msg.backValue);
                        break;
                }
            } catch (error) {
                // TODO: shouldn't we do something when there's an error?
            }
        }
    };

    //returns the mediator channel as eventType:eventName
    var getMediatorChannel = function (eventType, eventName) {
        return eventType + ':' + eventName;
    };

    // add the format extension to the String object
    if (!String.prototype.format) {
        String.prototype.format = function () {
            'use strict';
            var args = arguments;
            return this.replace(/\{\{|\}\}|\{(\d+)\}/g, function (m, n) {
                //Allow escaping of curly brackets with {{ or }}
                if (m === '{{') {
                    return '{';
                } else if (m === '}}') {
                    return '}';
                } else {
                    return args[n] != undefined ? args[n] : '{' + n + '}';
                }
            });
        };
    }

    var getNearestCities = function (nearByCitiesIdSelector, defaultNearByCitiesIdSeclector) {
        var datalayer = KBB.Page.getDataLayer(),
            location = datalayer.location,
            zipCode = location ? location.zip : '',
            nearByCitiesSelector = document.querySelector(nearByCitiesIdSelector),
            defaultNearByCities = document.querySelector(defaultNearByCitiesIdSeclector),
            url = nearByCitiesSelector ? nearByCitiesSelector.getAttribute('data-url') + '?zipCode=' + zipCode : '';

        if (zipCode !== '' && url !== '') {
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url);
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.send();
            xhr.onreadystatechange = function () {
                if (xhr.readyState === XMLHttpRequest.DONE && xhr.responseText.indexOf('ul') !== -1) {
                    nearByCitiesSelector.innerHTML = xhr.responseText;
                } else {
                    if (defaultNearByCities) {
                        defaultNearByCities.className = '';
                    }
                }
            };
        } else {
            if (defaultNearByCities) {
                defaultNearByCities.className = '';
            }
        }
    };
    var isInternalReferrerHostName = function () {
        var isInternal = false;
        var referrerUrl = document.referrer;
        if (referrerUrl !== '') {
            var referrerProtocol = referrerUrl.indexOf('://') > -1 ? referrerUrl.split('/')[0] : '';
            isInternal = Utils.getDomainFromUrl(referrerUrl) === window.location.hostname && referrerProtocol === window.location.protocol;
        }
        return isInternal ? 1 : 0;
    };

    return {
        init: function () {
            //setup mediator for processing message
            mediator = new Mediator();

            //setup listener for post messages
            if (window.addEventListener) {
                window.addEventListener('message', processMessages, false);
            } else {
                window.attachEvent('onmessage', processMessages);
            }
        },

        pushState: pushState,

        getMediator: function () {
            return mediator;
        },

        getMediatorChannel: getMediatorChannel,

        //bind to hideById
        bindToElementCollapse: function (elementId, func) {
            //Check to see if we already collapsed the element
            for (var i = 0, length = history.hiddenElements.length; i < length; i++) {
                if (history.hiddenElements[i].id === elementId) {
                    func.call(history.hiddenElements[i]);
                }
            }
            bindings[elementId] = func;
        },

        //constant defining eventTypes
        eventTypes: eventTypes,

        //hide the element and trigger an event
        hideById: hideById,

        //show the element and trigger an event
        showById: showById,

        //get ecoBoost data
        ecoBoost: ecoBoost,

        //change the body color
        updateBack: updateBack,

        //check shown ads
        getShowAdHistory: function (mediatorChannel) {
            return history.showAd[mediatorChannel];
        },

        // hidden ads
        getHiddenAdHistory: function (showElements) {
            var hiddenAds = [], elem;
            if (showElements) {
                hiddenAds = history.hiddenElements;
            }
            else {
                for (var elems in history.hiddenElements) {
                    elem = history.hiddenElements[elems];
                    if (/js\-has\-hidden\-parent/.test(elem.className)) {
                        hiddenAds.push(elem.id + '.js-has-hidden-parent');
                    }
                    else {
                        hiddenAds.push(elem.id);
                    }
                }
            }
            return hiddenAds;
        },

        //check resized ads
        getResizeAdHistory: function () {
            return history.resizeAd;
        },

        registerAdHandler: function (eventType, eventName, callback) {
            var channelName = Utils.getMediatorChannel(eventType, eventName),
                historyCheck = Utils.getShowAdHistory(channelName),
                subscriber;

            subscriber = Utils.getMediator().subscribe(channelName, callback);

            if (historyCheck) {
                callback(historyCheck);
            }

            return subscriber;
        },

        removeAdHandler: function (eventType, eventName, subscriberId) {
            var channelName = Utils.getMediatorChannel(eventType, eventName);
            history.showAd[channelName] = null;
            Utils.getMediator().remove(channelName, subscriberId);
        },

        //debounce a function.  This will make it so that no matter how many times this function is called,
        //will only execute once after the specified delay
        debounce: function (func, delay) {
            var throttler;

            return function (event) {
                clearTimeout(throttler);
                throttler = setTimeout(func.bind(this, event), delay);
            };
        },

        throttle: function (func, delay) {
            var throttler;
            var lastScrollFireTime = 0;

            return function (event) {
                var now = new Date().getTime();

                if (!throttler) {
                    if (now - lastScrollFireTime > (3 * delay)) {
                        func.call(this, event);   // fire immediately on first scroll
                        lastScrollFireTime = now;
                    }
                    throttler = setTimeout(function () {
                        throttler = null;
                        lastScrollFireTime = new Date().getTime();
                        func.call(this, event);
                    }, delay);
                }
            };
        },

        // jQuery free logic to determine if an element is in view
        elementInViewport: function (element, pageTop) {
            var actualPageTop = pageTop || 0;

            if (!element) {
                return false;
            }
            // Taken from: http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport/7557433#7557433
            var rect = element.getBoundingClientRect();
            var winHeight = window.innerHeight || document.documentElement.clientHeight;

            return (actualPageTop < rect.bottom && rect.bottom <= winHeight) ||
                (actualPageTop < rect.top && rect.top <= winHeight) ||
                (rect.top < winHeight && winHeight <= rect.bottom);
        },

        getParentWithSelector: function (element, selector) {
            var e = element;
            while (e) {
                if (Utils.matchesSelector(e, selector)) {
                    return e;
                }
                e = e.parentElement;
            }
            return null;
        },

        matchesSelector: function (element, selector) {
            var matchesSelector = element.matches || element.matchesSelector || element.webkitMatchesSelector || element.mozMatchesSelector || element.msMatchesSelector || element.oMatchesSelector;
            return matchesSelector.call(element, selector);
        },

        // taken from KBB.storage.js - need at the top of the page for T&T
        setCookie: function (name, value, expiration, path, domain) {
            var cookieFormat = '{0}={1};expires={2};path={3};domain={4}';
            try {
                expiration = getDateString(expiration, true);
                path = path || '/';
                domain = domain || '.kbb.com';

                document.cookie = cookieFormat.format(name, encodeURIComponent(value), expiration, path, domain);
                return true;
            } catch (e) {
                // Disable no-console rule here so that we can see the error when it's thrown
                console.log(JSON.stringify(e));  // eslint-disable-line no-console
            }
            return false;
        },

        //Extend function taken directly from jQuery (and modifying some of the utility functions
        extend: function () {
            var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {},
                i = 1,
                length = arguments.length,
                deep = false;

            // Handle a deep copy situation
            if (typeof target === 'boolean') {
                deep = target;
                target = arguments[1] || {};
                // skip the boolean and the target
                i = 2;
            }

            // Handle case when target is a string or something (possible in deep copy)
            if (typeof target !== 'object' && typeof target !== 'function') {
                target = {};
            }

            // extend jQuery itself if only one argument is passed
            if (length === i) {
                target = this;
                --i;
            }

            for (; i < length; i++) {
                // Only deal with non-null/undefined values
                if ((options = arguments[i]) != null) {
                    // Extend the base object
                    for (name in options) {
                        src = target[name];
                        copy = options[name];

                        // Prevent never-ending loop
                        if (target === copy) {
                            continue;
                        }

                        // Recurse if we're merging plain objects or arrays
                        if (deep && copy && (typeof copy === 'object' || (copyIsArray = Array.isArray(copy)))) {
                            if (copyIsArray) {
                                copyIsArray = false;
                                clone = src && Array.isArray(src) ? src : [];

                            } else {
                                clone = src && typeof src === 'object' ? src : {};
                            }

                            // Never move original objects, clone them
                            target[name] = Utils.extend(deep, clone, copy);

                            // Don't bring in undefined values
                        } else if (copy !== undefined) {
                            target[name] = copy;
                        }
                    }
                }
            }

            // Return the modified object
            return target;
        },

        eventMatches: function (event, eventToLookFor) {
            if (event) {
                var events = event instanceof Array ? event : [event];
                for (var i = 0; i < events.length; i++) {
                    //Add Namespace support later...
                    if (events[i] === eventToLookFor) {
                        return true;
                    }
                }
            }
            return false;
        },

        /**
        * Gets a query string parameter value
        * @param {string} queryString - query string
        * @returns {string} params - query string key values
        */
        parseQueryString: function (queryString) {
            var params = {}, queries, tempAr, i, l;

            if (queryString) {
                //remove the question mark if necessary
                if (queryString.length > 0 && queryString[0] === '?') {
                    queryString = queryString.substring(1);
                }

                // Split into key/value pairs
                queries = queryString.split('&');

                // Convert the array of strings into an object
                for (i = 0, l = queries.length; i < l; i++) {
                    tempAr = queries[i].split('=');
                    params[tempAr[0]] = tempAr[1];
                }
            }
            return params;
        },

        /**
         * Gets parameter value by name
         * @param {string} key - name of object key
         * @returns {string} value - value of object key
        */
        getParamByName: function (key) {
            var params = this.parseQueryString(window.location.href.substring(window.location.href.indexOf('?')));
            var value = '';

            if (typeof params !== 'undefined' && params[key]) {
                value = params[key];
            }
            return value;
        },

        /**
         * Takes in a full url and parses out the domain
         * @param {string} url: The complete url (http://www.yahoo.com/?qs1&qs2&qs3
         * @returns {string}: The domain part of the url (www.yahoo.com)
         */
        getDomainFromUrl: function (url) {
            var domain = '';

            // find & remove protocol (http, ftp, etc.) and to get the domain
            if (url.indexOf('://') > -1) {
                domain = url.split('/')[2];
            }
            else {
                domain = url.split('/')[0];
            }

            // find & remove port number
            domain = domain.split(':')[0];

            return domain;
        },

        //test and target
        tnt: {
            tests: {},

            addTest: function (id, testName) {
                if (!id || id == '') {
                    return;
                }
                id = id + '';
                testName = testName || id;
                if (!testName) {
                    return;
                }
                if (id.indexOf('^') > -1) {
                    var tests = id.split('^');
                    for (var i = 0; i < tests.length; i++) {
                        this.addTest(tests[i]);
                    }
                    return;
                }
                testName = (testName + '').toLowerCase();
                if (!Utils.tnt.tests[testName]) {
                    Utils.tnt.tests[testName] = { id: id };
                    this.updateProp39();
                }
                return Utils.tnt.tests[testName];
            },
            updateProp39: function () {
                var testIdArr = this.getTestIds(),
                    testIdStr = testIdArr.join('^');
                if (!testIdStr) {
                    s.prop39 = '';
                } else {
                    s.prop39 = testIdStr.toLowerCase();
                    if (KBB.DataLayer) {
                        KBB.DataLayer[KBB.DataLayer.length - 1].testids = testIdStr.toLowerCase();
                    }

                    if (KBB && KBB.Ads && KBB.Ads.setTestIds) {
                        KBB.Ads.setTestIds();
                    }
                }
            },
            getTestIds: function () {
                var array = [],
                    combinedTests = Utils.tnt.tests,
                    currentTestId,
                    currentTest;

                for (currentTestId in combinedTests) {
                    currentTest = combinedTests[currentTestId];
                    // If not already in the array and is also in the valid test ids array
                    if (array.indexOf(currentTest.id) === -1) {
                        array.push(currentTest.id);
                    }
                }
                return array;
            }
        },
        getNearestCities: getNearestCities,
        isInternalReferrerHostName: isInternalReferrerHostName
    };
})();

Utils.init();
;
/**
 * Utils for manipulating the DOM.  Going to require jQuery as a dependency since
 * so many DOM operations would be much easier compared to vanilla js.
 */
var DomUtils = (function () {
    'use strict';

    var self = {};

    self.matches = function (el, selector) {
        var matches = Element.prototype.matches ||
            Element.prototype.matchesSelector ||
            Element.prototype.mozMatchesSelector ||
            Element.prototype.msMatchesSelector ||
            Element.prototype.oMatchesSelector ||
            Element.prototype.webkitMatchesSelector ||
            function (s) {
                var m = (this.document || this.ownerDocument).querySelectorAll(s),
                    i = m.length;
                while (--i >= 0 && m.item(i) !== this) { }
                return i > -1;
            };

        return matches.apply(el, [selector]);
    };

    /**
     * Allows adding an deferred event listener
     */
    self.addEventListener = function (element, childSelector, eventName, handler) {
        if (element) {
            element.addEventListener(eventName, function (event) {
                var child = self.matchingParent(element, event.target, childSelector);
                if (child) {
                    handler.apply(child, [event]);
                }
            });
        }
    };

    self.matchingParent = function (rootElement, element, selector) {
        var child = element;
        while (child !== rootElement && child !== null) {
            if (self.matches(child, selector)) {
                return child;
            }
            child = child.parentElement;
        }

        return null;
    };

    /**
     * Scroll the body to the given x, y coordinates.  Specifically used for m1
     *
     */
    self.scrollTo = function ($contentContainer, x, y, delay, callback) {
        var $scrollingElement = $(self.getScrollingElement());

        $contentContainer.on('transitionend.scrollTo webkitTransitionEnd.scrollTo msTransitionEnd.scrollTo oTransitionEnd.scrollTo', function (event) {
            $contentContainer.off('.scrollTo');

            $contentContainer.css('transition', 'none');
            $contentContainer.css('-webkit-transition', 'none');
            $contentContainer.css('-webkit-transform', '');
            $contentContainer.css('transform', '');

            $scrollingElement.scrollTop(y);

            self.clearTransition($contentContainer);

            if (callback) {
                callback();
            }
        });

        self.setTransformTransition($contentContainer, (delay / 1000) + 's ease-in-out');
        self.setTransform($contentContainer, 0, ($scrollingElement.scrollTop() - y) + 'px', 0);
    };

    self.getScrollingElement = function () {
        if (document.scrollingElement) {
            return document.scrollingElement;
        }

        if (navigator.userAgent.indexOf('Firefox') > -1 || navigator.userAgent.indexOf('Trident/') > -1) {
            return document.documentElement;
        }

        return document.body;
    };

    self.setTransform = function ($element, x, y, z) {
        for (var i = 0; i < $element.length; i++) {
            var el = $element[i];

            el.style.transform = 'translate3d(' + x + ', ' + y + ', ' + z + ')';
            el.style.webkitTransform = 'translate3d(' + x + ', ' + y + ', ' + z + ')';
        }
    };

    self.setTransformTransition = function ($element, animation) {
        $element.each(function () {
            this.style.webkitTransition = '-webkit-transform ' + animation;
            this.style.transition = 'transform ' + animation;
        });
    };

    self.clearTransition = function ($element) {
        $element.each(function () {
            this.style.webkitTransition = '';
            this.style.transition = '';
        });
    };

    return self;
})();
;
//This file is loaded at the top of the page, so you will not have access to jQuery and the KBB namespaced functions
//Everything you write should be in plain javascript!

var Utils = Utils || {};
Utils.AdsApi = (function () {
    'use strict';

    var responseType = 'adApiResponse';

    var createApiResponse = function (msg) {
        var response = {};
        if (KBB && KBB.DataLayer && KBB.DataLayer.length > 0) {
            var dataLayer = KBB.DataLayer[0];

            // compile data based on dataFields
            if (msg.dataFields) {
                for (var i = 0; i < msg.dataFields.length; i++) {
                    var dataField = msg.dataFields[i];
                    switch (dataField) {
                        case 'year':
                            response.year = dataLayer.info.yearid ? dataLayer.info.yearid : '';
                            break;
                        case 'manufacturerId':
                            response.manufacturerId = dataLayer.info.manufacturer.id ? dataLayer.info.manufacturer.id : '';
                            break;
                        case 'modelId':
                            response.modelId = dataLayer.info.model.id ? dataLayer.info.model.id : '';
                            break;
                        case 'vehicleId':
                            response.vehicleId = dataLayer.info.vehicle.id ? dataLayer.info.vehicle.id : '';
                            break;
                        case 'zipCode':
                            response.zipCode = dataLayer.location.zip ? dataLayer.location.zip : '';
                            break;
                        case 'categoryId':
                            response.categoryId = dataLayer.info.categoryid ? dataLayer.info.categoryid : '';
                            break;
                        case 'ismobilelayout':
                            response.ismobilelayout = dataLayer.ismobilefirstlayout ? dataLayer.ismobilefirstlayout : false;
                            break;
                    }
                }
            }
        }
        response.type = responseType;
        
        return response;
    };

    var apiRequestHandler = function (event) {
        if (event.data) {
            // parse the data
            var msg = JSON.parse(event.data);

            // create the response
            var response = createApiResponse(msg);

            // send the response back to the source via post message
            event.source.postMessage(response, event.origin);
        }

    };

    return {
        init: function () {
            var channelName = Utils.getMediatorChannel(Utils.eventTypes.api, 'dataLayer');
            Utils.getMediator().subscribe(channelName, apiRequestHandler);
        }
    };
})();

Utils.AdsApi.init();
;
/*
 * Copyright (c) 2011, Yahoo! Inc.  All rights reserved.
 * Copyright (c) 2012, Log-Normal, Inc.  All rights reserved.
 * Copyright (c) 2014, SOASTA, Inc. All rights reserved.
 * Copyrights licensed under the BSD License. See the accompanying LICENSE.txt file for terms.
 */

/**
\file boomerang.js
boomerang measures various performance characteristics of your user's browsing
experience and beacons it back to your server.

\details
To use this you'll need a web site, lots of users and the ability to do
something with the data you collect.  How you collect the data is up to
you, but we have a few ideas.
*/

// Measure the time the script started
// This has to be global so that we don't wait for the entire
// BOOMR function to download and execute before measuring the
// time.  We also declare it without `var` so that we can later
// `delete` it.  This is the only way that works on Internet Explorer
BOOMR_start = new Date().getTime();

/**
 Check the value of document.domain and fix it if incorrect.
 This function is run at the top of boomerang, and then whenever
 init() is called.  If boomerang is running within an iframe, this
 function checks to see if it can access elements in the parent
 iframe.  If not, it will fudge around with document.domain until
 it finds a value that works.

 This allows customers to change the value of document.domain at
 any point within their page's load process, and we will adapt to
 it.
 */
function BOOMR_check_doc_domain(domain) {
	/*eslint no-unused-vars:0*/
	var test;

	// If domain is not passed in, then this is a global call
	// domain is only passed in if we call ourselves, so we
	// skip the frame check at that point
	if (!domain) {
		// If we're running in the main window, then we don't need this
		if (window.parent === window || !document.getElementById("boomr-if-as")) {
			return;// true;	// nothing to do
		}

		if (window.BOOMR && BOOMR.boomerang_frame && BOOMR.window) {
			try {
				// If document.domain is changed during page load (from www.blah.com to blah.com, for example),
				// BOOMR.window.location.href throws "Permission Denied" in IE.
				// Resetting the inner domain to match the outer makes location accessible once again
				if (BOOMR.boomerang_frame.document.domain !== BOOMR.window.document.domain) {
					BOOMR.boomerang_frame.document.domain = BOOMR.window.document.domain;
				}
			}
			catch(err) {
				if (!BOOMR.isCrossOriginError(err)) {
					BOOMR.addError(err, "BOOMR_check_doc_domain.domainFix");
				}
			}
		}
		domain = document.domain;
	}

	if (domain.indexOf(".") === -1) {
		return;// false;	// not okay, but we did our best
	}

	// 1. Test without setting document.domain
	try {
		test = window.parent.document;
		return;// test !== undefined;	// all okay
	}
	// 2. Test with document.domain
	catch (err) {
		document.domain = domain;
	}
	try {
		test = window.parent.document;
		return;// test !== undefined;	// all okay
	}
	// 3. Strip off leading part and try again
	catch (err) {
		domain = domain.replace(/^[\w\-]+\./, "");
	}

	BOOMR_check_doc_domain(domain);
}

BOOMR_check_doc_domain();


// beaconing section
// the parameter is the window
(function(w) {

	var impl, boomr, d, myurl, createCustomEvent, dispatchEvent, visibilityState, visibilityChange, orig_w = w;

	// This is the only block where we use document without the w. qualifier
	if (w.parent !== w
			&& document.getElementById("boomr-if-as")
			&& document.getElementById("boomr-if-as").nodeName.toLowerCase() === "script") {
		w = w.parent;
		myurl = document.getElementById("boomr-if-as").src;
	}

	d = w.document;

	// Short namespace because I don't want to keep typing BOOMERANG
	if (!w.BOOMR) { w.BOOMR = {}; }
	BOOMR = w.BOOMR;
	// don't allow this code to be included twice
	if (BOOMR.version) {
		return;
	}

	BOOMR.version = "0.9";
	BOOMR.window = w;
	BOOMR.boomerang_frame = orig_w;

	if (!BOOMR.plugins) { BOOMR.plugins = {}; }

	// CustomEvent proxy for IE9 & 10 from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent
	(function() {
		try {
			if (new w.CustomEvent("CustomEvent") !== undefined) {
				createCustomEvent = function(e_name, params) {
					return new w.CustomEvent(e_name, params);
				};
			}
		}
		catch (ignore) {
			// empty
		}

		try {
			if (!createCustomEvent && d.createEvent && d.createEvent( "CustomEvent" )) {
				createCustomEvent = function(e_name, params) {
					var evt = d.createEvent( "CustomEvent" );
					params = params || { cancelable: false, bubbles: false };
					evt.initCustomEvent( e_name, params.bubbles, params.cancelable, params.detail );

					return evt;
				};
			}
		}
		catch (ignore) {
			// empty
		}

		if (!createCustomEvent && d.createEventObject) {
			createCustomEvent = function(e_name, params) {
				var evt = d.createEventObject();
				evt.type = evt.propertyName = e_name;
				evt.detail = params.detail;

				return evt;
			};
		}

		if (!createCustomEvent) {
			createCustomEvent = function() { return undefined; };
		}
	}());

	/**
	 dispatch a custom event to the browser
	 @param e_name	The custom event name that consumers can subscribe to
	 @param e_data	Any data passed to subscribers of the custom event via the `event.detail` property
	 @param async	By default, custom events are dispatched immediately.
			Set to true if the event should be dispatched once the browser has finished its current
			JavaScript execution.
	 */
	dispatchEvent = function(e_name, e_data, async) {
		var ev = createCustomEvent(e_name, {"detail": e_data});
		if (!ev) {
			return;
		}

		function dispatch() {
			if (d.dispatchEvent) {
				d.dispatchEvent(ev);
			}
			else if (d.fireEvent) {
				d.fireEvent("onpropertychange", ev);
			}
		}

		if (async) {
			BOOMR.setImmediate(dispatch);
		}
		else {
			dispatch();
		}
	};

	// visibilitychange is useful to detect if the page loaded through prerender
	// or if the page never became visible
	// http://www.w3.org/TR/2011/WD-page-visibility-20110602/
	// http://www.nczonline.net/blog/2011/08/09/introduction-to-the-page-visibility-api/
	// https://developer.mozilla.org/en-US/docs/Web/Guide/User_experience/Using_the_Page_Visibility_API

	// Set the name of the hidden property and the change event for visibility
	if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
		visibilityState = "visibilityState";
		visibilityChange = "visibilitychange";
	}
	else if (typeof document.mozHidden !== "undefined") {
		visibilityState = "mozVisibilityState";
		visibilityChange = "mozvisibilitychange";
	}
	else if (typeof document.msHidden !== "undefined") {
		visibilityState = "msVisibilityState";
		visibilityChange = "msvisibilitychange";
	}
	else if (typeof document.webkitHidden !== "undefined") {
		visibilityState = "webkitVisibilityState";
		visibilityChange = "webkitvisibilitychange";
	}


	// impl is a private object not reachable from outside the BOOMR object
	// users can set properties by passing in to the init() method
	impl = {
		// properties
		beacon_url: "",
		// beacon request method, either GET, POST or AUTO. AUTO will check the
		// request size then use GET if the request URL is less than 2000 chars
		// otherwise it will fall back to a POST request.
		beacon_type: "AUTO",
		// strip out everything except last two parts of hostname.
		// This doesn't work well for domains that end with a country tld,
		// but we allow the developer to override site_domain for that.
		// You can disable all cookies by setting site_domain to a falsy value
		site_domain: w.location.hostname.
					replace(/.*?([^.]+\.[^.]+)\.?$/, "$1").
					toLowerCase(),
		//! User's ip address determined on the server.  Used for the BA cookie
		user_ip: "",
		// Whether or not to send beacons on page load
		autorun: true,

		strip_query_string: false,

		onloadfired: false,

		handlers_attached: false,
		events: {
			"page_ready": [],
			"page_unload": [],
			"before_unload": [],
			"dom_loaded": [],
			"visibility_changed": [],
			"before_beacon": [],
			"onbeacon": [],
			"xhr_load": [],
			"click": [],
			"form_submit": []
		},

		public_events: {
			"before_beacon": "onBeforeBoomerangBeacon",
			"onbeacon": "onBoomerangBeacon",
			"onboomerangloaded": "onBoomerangLoaded"
		},

		vars: {},

		errors: {},

		disabled_plugins: {},

		xb_handler: function(type) {
			return function(ev) {
				var target;
				if (!ev) { ev = w.event; }
				if (ev.target) { target = ev.target; }
				else if (ev.srcElement) { target = ev.srcElement; }
				if (target.nodeType === 3) {// defeat Safari bug
					target = target.parentNode;
				}

				// don't capture events on flash objects
				// because of context slowdowns in PepperFlash
				if (target && target.nodeName.toUpperCase() === "OBJECT" && target.type === "application/x-shockwave-flash") {
					return;
				}
				impl.fireEvent(type, target);
			};
		},

		fireEvent: function(e_name, data) {
			var i, handler, handlers;

			e_name = e_name.toLowerCase();

			if (!this.events.hasOwnProperty(e_name)) {
				return;// false;
			}

			if (this.public_events.hasOwnProperty(e_name)) {
				dispatchEvent(this.public_events[e_name], data);
			}

			handlers = this.events[e_name];

			for (i=0; i<handlers.length; i++) {
				try {
					handler = handlers[i];
					handler.fn.call(handler.scope, data, handler.cb_data);
				}
				catch (err) {
					BOOMR.addError(err, "fireEvent." + e_name + "<" + i + ">");
				}
			}

			return;// true;
		}
	};


	// We create a boomr object and then copy all its properties to BOOMR so that
	// we don't overwrite anything additional that was added to BOOMR before this
	// was called... for example, a plugin.
	boomr = {
		t_lstart: null,
		t_start: BOOMR_start,
		t_end: null,
		//! t_pload: Value of the BOOMR_onload set in the host page
		t_onload: undefined,

		url: myurl,

		// Utility functions
		utils: {
			objectToString: function(o, separator, nest_level) {
				var value = [], k;

				if (!o || typeof o !== "object") {
					return o;
				}
				if (separator === undefined) {
					separator="\n\t";
				}
				if (!nest_level) {
					nest_level=0;
				}

				if (Object.prototype.toString.call(o) === "[object Array]") {
					for (k=0; k<o.length; k++) {
						if (nest_level > 0 && o[k] !== null && typeof o[k] === "object") {
							value.push(
								this.objectToString(
									o[k],
									separator + (separator === "\n\t" ? "\t" : ""),
									nest_level-1
								)
							);
						}
						else {
							if (separator === "&") {
								value.push(encodeURIComponent(o[k]));
							}
							else {
								value.push(o[k]);
							}
						}
					}
					separator = ",";
				}
				else {
					for (k in o) {
						if (Object.prototype.hasOwnProperty.call(o, k)) {
							if (nest_level > 0 && o[k] !== null && typeof o[k] === "object") {
								value.push(encodeURIComponent(k) + "=" +
									this.objectToString(
										o[k],
										separator + (separator === "\n\t" ? "\t" : ""),
										nest_level-1
									)
								);
							}
							else {
								if (separator === "&") {
									value.push(encodeURIComponent(k) + "=" + encodeURIComponent(o[k]));
								}
								else {
									value.push(k + "=" + o[k]);
								}
							}
						}
					}
				}

				return value.join(separator);
			},

			getCookie: function(name) {
				if (!name) {
					return null;
				}

				name = " " + name + "=";

				var i, cookies;
				cookies = " " + d.cookie + ";";
				if ( (i=cookies.indexOf(name)) >= 0 ) {
					i += name.length;
					cookies = cookies.substring(i, cookies.indexOf(";", i)).replace(/^"/, "").replace(/"$/, "");
					return cookies;
				}

				return null;
			},

			setCookie: function(name, subcookies, max_age) {
				var value, nameval, savedval, c, exp;

				if (!name || !impl.site_domain) {
					BOOMR.debug("No cookie name or site domain: " + name + "/" + impl.site_domain);
					return false;
				}

				value = this.objectToString(subcookies, "&");
				nameval = name + "=\"" + value + "\"";

				c = [nameval, "path=/", "domain=" + impl.site_domain];
				if (max_age) {
					exp = new Date();
					exp.setTime(exp.getTime() + max_age*1000);
					exp = exp.toGMTString();
					c.push("expires=" + exp);
				}

				if ( nameval.length < 500 ) {
					d.cookie = c.join("; ");
					// confirm cookie was set (could be blocked by user's settings, etc.)
					savedval = this.getCookie(name);
					if (value === savedval) {
						return true;
					}
					BOOMR.warn("Saved cookie value doesn't match what we tried to set:\n" + value + "\n" + savedval);
				}
				else {
					BOOMR.warn("Cookie too long: " + nameval.length + " " + nameval);
				}

				return false;
			},

			getSubCookies: function(cookie) {
				var cookies_a,
				    i, l, kv,
				    gotcookies=false,
				    cookies={};

				if (!cookie) {
					return null;
				}

				if (typeof cookie !== "string") {
					BOOMR.debug("TypeError: cookie is not a string: " + typeof cookie);
					return null;
				}

				cookies_a = cookie.split("&");

				for (i=0, l=cookies_a.length; i<l; i++) {
					kv = cookies_a[i].split("=");
					if (kv[0]) {
						kv.push("");	// just in case there's no value
						cookies[decodeURIComponent(kv[0])] = decodeURIComponent(kv[1]);
						gotcookies=true;
					}
				}

				return gotcookies ? cookies : null;
			},

			removeCookie: function(name) {
				return this.setCookie(name, {}, -86400);
			},

			cleanupURL: function(url) {
				if (!url || Object.prototype.toString.call(url) === "[object Array]") {
					return "";
				}
				if (impl.strip_query_string) {
					return url.replace(/\?.*/, "?qs-redacted");
				}
				return url;
			},

			hashQueryString: function(url, stripHash) {
				if (!url) {
					return url;
				}
				if (!url.match) {
					BOOMR.addError("TypeError: Not a string", "hashQueryString", typeof url);
					return "";
				}
				if (url.match(/^\/\//)) {
					url = location.protocol + url;
				}
				if (!url.match(/^(https?|file):/)) {
					BOOMR.error("Passed in URL is invalid: " + url);
					return "";
				}
				if (stripHash) {
					url = url.replace(/#.*/, "");
				}
				if (!BOOMR.utils.MD5) {
					return url;
				}
				return url.replace(/\?([^#]*)/, function(m0, m1) { return "?" + (m1.length > 10 ? BOOMR.utils.MD5(m1) : m1); });
			},

			pluginConfig: function(o, config, plugin_name, properties) {
				var i, props=0;

				if (!config || !config[plugin_name]) {
					return false;
				}

				for (i=0; i<properties.length; i++) {
					if (config[plugin_name][properties[i]] !== undefined) {
						o[properties[i]] = config[plugin_name][properties[i]];
						props++;
					}
				}

				return (props>0);
			},
			/**
			 * `filter` for arrays
			 *
			 * @private
			 * @param {Array} array The array to iterate over.
			 * @param {Function} predicate The function invoked per iteration.
			 * @returns {Array} Returns the new filtered array.
			 */
			arrayFilter: function(array, predicate) {
				var result = [];

				if (typeof array.filter === "function") {
					result = array.filter(predicate);
				}
				else {
					var index = -1,
					    length = array.length,
					    value;

					while (++index < length) {
						value = array[index];
						if (predicate(value, index, array)) {
							result[result.length] = value;
						}
					}
				}
				return result;
			},
			/**
			 Add a MutationObserver for a given element and terminate after `timeout`ms.
			 @param el		DOM element to watch for mutations
			 @param config		MutationObserverInit object (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver#MutationObserverInit)
			 @param timeout		Number of milliseconds of no mutations after which the observer should be automatically disconnected
						If set to a falsy value, the observer will wait indefinitely for Mutations.
			 @param callback	Callback function to call either on timeout or if mutations are detected.  The signature of this method is:
							function(mutations, callback_data)
						Where:
							mutations is the list of mutations detected by the observer or `undefined` if the observer timed out
							callback_data is the passed in `callback_data` parameter without modifications

						The callback function may return a falsy value to disconnect the observer after it returns, or a truthy value to
						keep watching for mutations. If the return value is numeric and greater than 0, then this will be the new timeout
						if it is boolean instead, then the timeout will not fire any more so the caller MUST call disconnect() at some point
			 @param callback_data	Any data to be passed to the callback function as its second parameter
			 @param callback_ctx	An object that represents the `this` object of the `callback` method.  Leave unset the callback function is not a method of an object

			 @returns	- `null` if a MutationObserver could not be created OR
					- An object containing the observer and the timer object:
					  { observer: <MutationObserver>, timer: <Timeout Timer if any> }

					The caller can use this to disconnect the observer at any point by calling `retval.observer.disconnect()`
					Note that the caller should first check to see if `retval.observer` is set before calling `disconnect()` as it may
					have been cleared automatically.
			 */
			addObserver: function(el, config, timeout, callback, callback_data, callback_ctx) {
				var o = {observer: null, timer: null};

				if (!window.MutationObserver || !callback || !el) {
					return null;
				}

				function done(mutations) {
					var run_again=false;

					if (o.timer) {
						clearTimeout(o.timer);
						o.timer = null;
					}

					if (callback) {
						run_again = callback.call(callback_ctx, mutations, callback_data);

						if (!run_again) {
							callback = null;
						}
					}

					if (!run_again && o.observer) {
						o.observer.disconnect();
						o.observer = null;
					}

					if (typeof run_again === "number" && run_again > 0) {
						o.timer = setTimeout(done, run_again);
					}
				}

				o.observer = new MutationObserver(done);

				if (timeout) {
					o.timer = setTimeout(done, o.timeout);
				}

				o.observer.observe(el, config);

				return o;
			},

			addListener: function(el, type, fn) {
				if (el.addEventListener) {
					el.addEventListener(type, fn, false);
				}
				else if (el.attachEvent) {
					el.attachEvent( "on" + type, fn );
				}
			},

			removeListener: function(el, type, fn) {
				if (el.removeEventListener) {
					el.removeEventListener(type, fn, false);
				}
				else if (el.detachEvent) {
					el.detachEvent("on" + type, fn);
				}
			},

			pushVars: function(form, vars, prefix) {
				var k, i, l=0, input;

				for (k in vars) {
					if (vars.hasOwnProperty(k)) {
						if (Object.prototype.toString.call(vars[k]) === "[object Array]") {
							for (i = 0; i < vars[k].length; ++i) {
								l += BOOMR.utils.pushVars(form, vars[k][i], k + "[" + i + "]");
							}
						}
						else {
							input = document.createElement("input");
							input.type = "hidden";	// we need `hidden` to preserve newlines. see commit message for more details
							input.name = (prefix ? (prefix + "[" + k + "]") : k);
							input.value = (vars[k]===undefined || vars[k]===null ? "" : vars[k]);

							form.appendChild(input);

							l += encodeURIComponent(input.name).length + encodeURIComponent(input.value).length + 2;
						}
					}
				}

				return l;
			},

			sendData: function(form, method) {
				var input = document.createElement("input"),
				    urls = [ impl.beacon_url ];

				form.method = method;
				form.id = "beacon_form";

				// TODO: Determine if we want to send as JSON
				//if (window.JSON) {
				//	form.innerHTML = "";
				//	form.enctype = "text/plain";
				//	input.name = "data";
				//	input.value = JSON.stringify(impl.vars);
				//	form.appendChild(input);
				//} else {
				form.enctype = "application/x-www-form-urlencoded";
				//}

				if (impl.secondary_beacons && impl.secondary_beacons.length) {
					urls.push.apply(urls, impl.secondary_beacons);
				}


				function remove(id) {
					var el = document.getElementById(id);
					if (el) {
						el.parentNode.removeChild(el);
					}
				}

				function submit() {
					/*eslint-disable no-script-url*/
					var iframe,
					    name = "boomerang_post-" + encodeURIComponent(form.action) + "-" + Math.random();

					// ref: http://terminalapp.net/submitting-a-form-with-target-set-to-a-script-generated-iframe-on-ie/
					try {
						iframe = document.createElement('<iframe name="' + name + '">');	// IE <= 8
					}
					catch (ignore) {
						iframe = document.createElement("iframe");				// everything else
					}

					form.action = urls.shift();
					iframe.name = iframe.id = name;

					// IE Edge hangs for a minute on some sites when using form.submit().  This
					// can be avoided by not setting the form.target, and adding the form to the
					// iframe instead of the document.
					iframe.style.display = form.style.display = "none";
					iframe.src="javascript:false";

					remove(iframe.id);
					remove(form.id);

					document.body.appendChild(iframe);

					// Add the form to the iframe
					var iFrmDocument = (iframe.contentWindow || iframe.contentDocument);
					if (iFrmDocument.document) {
						iFrmDocument = iFrmDocument.document;
					}
					if (iFrmDocument.body) {
						iFrmDocument.body.appendChild(form);
					}
					else {
						//body may be null, so add to the document
						iFrmDocument.appendChild(form);
					}

					try {
						form.submit();
					}
					catch (ignore) {
						// empty
					}

					if (urls.length) {
						BOOMR.setImmediate(submit);
					}

					setTimeout(function() { remove(iframe.id); }, 10000);
				}

				submit();
			}
		},

		init: function(config) {
			var i, k,
			    properties = ["beacon_url", "beacon_type", "site_domain", "user_ip", "strip_query_string", "secondary_beacons", "autorun"];

			BOOMR_check_doc_domain();

			if (!config) {
				config = {};
			}

			if (config.primary && impl.handlers_attached) {
				return this;
			}

			if (config.log !== undefined) {
				this.log = config.log;
			}
			if (!this.log) {
				this.log = function(/* m,l,s */) {};
			}

			for (k in this.plugins) {
				if (this.plugins.hasOwnProperty(k)) {
					// config[plugin].enabled has been set to false
					if ( config[k]
						&& config[k].hasOwnProperty("enabled")
						&& config[k].enabled === false
					) {
						impl.disabled_plugins[k] = 1;

						if (typeof this.plugins[k].disable === "function") {
							this.plugins[k].disable();
						}

						continue;
					}

					// plugin was previously disabled
					if (impl.disabled_plugins[k]) {

						// and has not been explicitly re-enabled
						if ( !config[k]
							|| !config[k].hasOwnProperty("enabled")
							|| config[k].enabled !== true
						) {
							continue;
						}

						if (typeof this.plugins[k].enable === "function") {
							this.plugins[k].enable();
						}

						// plugin is now enabled
						delete impl.disabled_plugins[k];
					}

					// plugin exists and has an init method
					if (typeof this.plugins[k].init === "function") {
						try {
							this.plugins[k].init(config);
						}
						catch (err) {
							BOOMR.addError(err, k + ".init");
						}
					}
				}
			}

			for (i=0; i<properties.length; i++) {
				if (config[properties[i]] !== undefined) {
					impl[properties[i]] = config[properties[i]];
				}
			}

			if (impl.handlers_attached) {
				return this;
			}

			// The developer can override onload by setting autorun to false
			if (!impl.onloadfired && (config.autorun === undefined || config.autorun !== false)) {
				if (d.readyState && d.readyState === "complete") {
					BOOMR.loadedLate = true;
					this.setImmediate(BOOMR.page_ready_autorun, null, null, BOOMR);
				}
				else {
					if (w.onpagehide || w.onpagehide === null) {
						BOOMR.utils.addListener(w, "pageshow", BOOMR.page_ready_autorun);
					}
					else {
						BOOMR.utils.addListener(w, "load", BOOMR.page_ready_autorun);
					}
				}
			}

			BOOMR.utils.addListener(w, "DOMContentLoaded", function() { impl.fireEvent("dom_loaded"); });

			(function() {
				var forms, iterator;
				if (visibilityChange !== undefined) {
					BOOMR.utils.addListener(d, visibilityChange, function() { impl.fireEvent("visibility_changed"); });

					// record the last time each visibility state occurred
					BOOMR.subscribe("visibility_changed", function() {
						BOOMR.lastVisibilityEvent[BOOMR.visibilityState()] = BOOMR.now();
					});
				}

				BOOMR.utils.addListener(d, "mouseup", impl.xb_handler("click"));

				forms = d.getElementsByTagName("form");
				for (iterator = 0; iterator < forms.length; iterator++) {
					BOOMR.utils.addListener(forms[iterator], "submit", impl.xb_handler("form_submit"));
				}

				if (!w.onpagehide && w.onpagehide !== null) {
					// This must be the last one to fire
					// We only clear w on browsers that don't support onpagehide because
					// those that do are new enough to not have memory leak problems of
					// some older browsers
					BOOMR.utils.addListener(w, "unload", function() { BOOMR.window=w=null; });
				}
			}());

			impl.handlers_attached = true;
			return this;
		},
		/**
		 * Sends the page_ready beacon only if 'autorun' is still true after config.js
		 * arrives.
		 */
		page_ready_autorun: function(ev) {
			if (impl.autorun) {
				BOOMR.page_ready(ev);
			}
		},

		// The page dev calls this method when they determine the page is usable.
		// Only call this if autorun is explicitly set to false
		page_ready: function(ev) {
			if (!ev) { ev = w.event; }
			if (!ev) { ev = { name: "load" }; }
			if (impl.onloadfired) {
				return this;
			}
			impl.fireEvent("page_ready", ev);
			impl.onloadfired = true;
			return this;
		},

		setImmediate: function(fn, data, cb_data, cb_scope) {
			var cb, cstack;

			// DEBUG: This is to help debugging, we'll see where setImmediate calls were made from
			if (typeof Error !== "undefined") {
				cstack = new Error();
				cstack = cstack.stack ? cstack.stack.replace(/^Error/, "Called") : undefined;
			}
			// END-DEBUG

			cb = function() {
				fn.call(cb_scope || null, data, cb_data || {}, cstack);
				cb=null;
			};

			if (w.setImmediate) {
				w.setImmediate(cb);
			}
			else if (w.msSetImmediate) {
				w.msSetImmediate(cb);
			}
			else if (w.webkitSetImmediate) {
				w.webkitSetImmediate(cb);
			}
			else if (w.mozSetImmediate) {
				w.mozSetImmediate(cb);
			}
			else {
				setTimeout(cb, 10);
			}
		},

		now: (function() {
			try {
				if ("performance" in window && window.performance && window.performance.now) {
					return function() {
						return Math.round(window.performance.now() + window.performance.timing.navigationStart);
					};
				}
			}
			catch (ignore) {
				// empty
			}

			return Date.now || function() { return new Date().getTime(); };
		}()),

		visibilityState: ( visibilityState === undefined ? function() { return "visible"; } : function() { return d[visibilityState]; } ),

		lastVisibilityEvent: {},

		subscribe: function(e_name, fn, cb_data, cb_scope) {
			var i, handler, ev;

			e_name = e_name.toLowerCase();

			if (!impl.events.hasOwnProperty(e_name)) {
				return this;
			}

			ev = impl.events[e_name];

			// don't allow a handler to be attached more than once to the same event
			for (i=0; i<ev.length; i++) {
				handler = ev[i];
				if (handler && handler.fn === fn && handler.cb_data === cb_data && handler.scope === cb_scope) {
					return this;
				}
			}
			ev.push({ "fn": fn, "cb_data": cb_data || {}, "scope": cb_scope || null });

			// attaching to page_ready after onload fires, so call soon
			if (e_name === "page_ready" && impl.onloadfired) {
				this.setImmediate(fn, null, cb_data, cb_scope);
			}

			// Attach unload handlers directly to the window.onunload and
			// window.onbeforeunload events. The first of the two to fire will clear
			// fn so that the second doesn't fire. We do this because technically
			// onbeforeunload is the right event to fire, but all browsers don't
			// support it.  This allows us to fall back to onunload when onbeforeunload
			// isn't implemented
			if (e_name === "page_unload" || e_name === "before_unload") {
				(function() {
					var unload_handler, evt_idx = ev.length;

					unload_handler = function(evt) {
								if (fn) {
									fn.call(cb_scope, evt || w.event, cb_data);
								}

								// If this was the last unload handler, we'll try to send the beacon immediately after it is done
								// The beacon will only be sent if one of the handlers has queued it
								if (e_name === "page_unload" && evt_idx === impl.events[e_name].length) {
									BOOMR.real_sendBeacon();
								}
							};

					if (e_name === "page_unload") {
						// pagehide is for iOS devices
						// see http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/
						if (w.onpagehide || w.onpagehide === null) {
							BOOMR.utils.addListener(w, "pagehide", unload_handler);
						}
						else {
							BOOMR.utils.addListener(w, "unload", unload_handler);
						}
					}
					BOOMR.utils.addListener(w, "beforeunload", unload_handler);
				}());
			}

			return this;
		},

		addError: function(err, src, extra) {
			var str;
			if (typeof err !== "string") {
				str = String(err);
				if (str.match(/^\[object/)) {
					str = err.name + ": " + (err.description || err.message).replace(/\r\n$/, "");
				}
				err = str;
			}
			if (src !== undefined) {
				err = "[" + src + ":" + BOOMR.now() + "] " + err;
			}
			if (extra) {
				err += ":: " + extra;
			}

			if (impl.errors[err]) {
				impl.errors[err]++;
			}
			else {
				impl.errors[err] = 1;
			}
		},

		isCrossOriginError: function(err) {
			// These are expected for cross-origin iframe access, although the Internet Explorer check will only
			// work for browsers using English.
			return err.name === "SecurityError" ||
				(err.name === "TypeError" && err.message === "Permission denied") ||
				(err.name === "Error" && err.message && err.message.match(/^(Permission|Access is) denied/));
		},

		addVar: function(name, value) {
			if (typeof name === "string") {
				impl.vars[name] = value;
			}
			else if (typeof name === "object") {
				var o = name, k;
				for (k in o) {
					if (o.hasOwnProperty(k)) {
						impl.vars[k] = o[k];
					}
				}
			}
			return this;
		},

		removeVar: function(arg0) {
			var i, params;
			if (!arguments.length) {
				return this;
			}

			if (arguments.length === 1
					&& Object.prototype.toString.apply(arg0) === "[object Array]") {
				params = arg0;
			}
			else {
				params = arguments;
			}

			for (i=0; i<params.length; i++) {
				if (impl.vars.hasOwnProperty(params[i])) {
					delete impl.vars[params[i]];
				}
			}

			return this;
		},

		hasVar: function(name) {
			return impl.vars.hasOwnProperty(name);
		},

		requestStart: function(name) {
			var t_start = BOOMR.now();
			BOOMR.plugins.RT.startTimer("xhr_" + name, t_start);

			return {
				loaded: function(data) {
					BOOMR.responseEnd(name, t_start, data);
				}
			};
		},

		responseEnd: function(name, t_start, data) {
			if (typeof name === "object" && name.url) {
				impl.fireEvent("xhr_load", name);
			}
			else {
				BOOMR.plugins.RT.startTimer("xhr_" + name, t_start);
				impl.fireEvent("xhr_load", {
					"name": "xhr_" + name,
					"data": data
				});
			}
		},

		//
		// uninstrumentXHR and instrumentXHR are stubs that will be replaced
		// by auto_xhr.js if active.
		//
		/**
		 * Undo XMLHttpRequest instrumentation and reset the original
		 */
		uninstrumentXHR: function() {
		},
		/**
		 * Instrument all requests made via XMLHttpRequest to send beacons
		 * This is implemented in plugins/auto_xhr.js
		 */
		instrumentXHR: function() { },

		sendBeacon: function(beacon_url_override) {
			// This plugin wants the beacon to go somewhere else,
			// so update the location
			if (beacon_url_override) {
				impl.beacon_url = beacon_url_override;
			}

			if (!impl.beaconQueued) {
				impl.beaconQueued = true;
				BOOMR.setImmediate(BOOMR.real_sendBeacon, null, null, BOOMR);
			}

			return true;
		},

		real_sendBeacon: function() {
			var k, form, furl, img, length=0, errors=[], url, nparams=0;

			if (!impl.beaconQueued) {
				return false;
			}

			impl.beaconQueued = false;

			BOOMR.debug("Checking if we can send beacon");

			// At this point someone is ready to send the beacon.  We send
			// the beacon only if all plugins have finished doing what they
			// wanted to do
			for (k in this.plugins) {
				if (this.plugins.hasOwnProperty(k)) {
					if (impl.disabled_plugins[k]) {
						continue;
					}
					if (!this.plugins[k].is_complete()) {
						BOOMR.debug("Plugin " + k + " is not complete, deferring beacon send");
						return false;
					}
				}
			}

			// For SPA apps, don't strip hashtags as some SPA frameworks use #s for tracking routes
			// instead of History pushState() APIs. Use d.URL instead of location.href because of a
			// Safari bug.
			var isSPA = impl.vars["http.initiator"] === "spa";
			var pgu = isSPA ? d.URL : d.URL.replace(/#.*/, "");
			impl.vars.pgu = BOOMR.utils.cleanupURL(pgu);

			// Use the current document.URL if it hasn't already been set, or for SPA apps,
			// on each new beacon (since each SPA soft navigation might change the URL)
			if (!impl.vars.u || isSPA) {
				impl.vars.u = impl.vars.pgu;
			}

			if (impl.vars.pgu === impl.vars.u) {
				delete impl.vars.pgu;
			}

			impl.vars.v = BOOMR.version;

			if (BOOMR.visibilityState()) {
				impl.vars["vis.st"] = BOOMR.visibilityState();
				if (BOOMR.lastVisibilityEvent.visible) {
					impl.vars["vis.lv"] = BOOMR.now() - BOOMR.lastVisibilityEvent.visible;
				}
				if (BOOMR.lastVisibilityEvent.hidden) {
					impl.vars["vis.lh"] = BOOMR.now() - BOOMR.lastVisibilityEvent.hidden;
				}
			}

			impl.vars["ua.plt"] = navigator.platform;
			impl.vars["ua.vnd"] = navigator.vendor;

			if (w !== window) {
				impl.vars["if"] = "";
			}

			for (k in impl.errors) {
				if (impl.errors.hasOwnProperty(k)) {
					errors.push(k + (impl.errors[k] > 1 ? " (*" + impl.errors[k] + ")" : ""));
				}
			}

			if (errors.length > 0) {
				impl.vars.errors = errors.join("\n");
			}

			impl.errors = {};

			// If we reach here, all plugins have completed
			impl.fireEvent("before_beacon", impl.vars);

			// Don't send a beacon if no beacon_url has been set
			// you would do this if you want to do some fancy beacon handling
			// in the `before_beacon` event instead of a simple GET request
			BOOMR.debug("Ready to send beacon: " + BOOMR.utils.objectToString(impl.vars));
			if (!impl.beacon_url) {
				BOOMR.debug("No beacon URL, so skipping.");
				return true;
			}

			if (!BOOMR.hasVar("restiming")) {
				// Use an Image beacon if we're not sending ResourceTiming data

				// if there are already url parameters in the beacon url,
				// change the first parameter prefix for the boomerang url parameters to &

				url = [];

				for (k in impl.vars) {
					if (impl.vars.hasOwnProperty(k)) {
						nparams++;
						url.push(encodeURIComponent(k)
							+ "="
							+ (
								impl.vars[k]===undefined || impl.vars[k]===null
								? ""
								: encodeURIComponent(impl.vars[k])
							)
						);
					}
				}

				furl = impl.beacon_url + ((impl.beacon_url.indexOf("?") > -1)?"&":"?") + url.join("&");
			}
			else {
				form = document.createElement("form");
				length = BOOMR.utils.pushVars(form, impl.vars);
			}

			// If we reach here, we've transferred all vars to the beacon URL.
			impl.fireEvent("onbeacon", impl.vars);

			if (length === 0 && nparams === 0) {
				// do not make the request if there is no data
				return this;
			}

			if (nparams) {
				img = new Image();
				img.src=furl;

				if (impl.secondary_beacons) {
					for (k = 0; k<impl.secondary_beacons.length; k++) {
						furl = impl.secondary_beacons[k] + "?" + url.join("&");
						img = new Image();
						img.src=furl;
					}
				}
			}
			else {
				// using 2000 here as a de facto maximum URL length based on:
				// http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
				BOOMR.utils.sendData(form, impl.beacon_type === "AUTO" ? (length > 2000 ? "POST" : "GET") : "POST");
			}

			return true;
		}

	};

	delete BOOMR_start;

	if (typeof BOOMR_lstart === "number") {
		boomr.t_lstart = BOOMR_lstart;
		delete BOOMR_lstart;
	}
	else if (typeof BOOMR.window.BOOMR_lstart === "number") {
		boomr.t_lstart = BOOMR.window.BOOMR_lstart;
	}

	if (typeof BOOMR.window.BOOMR_onload === "number") {
		boomr.t_onload = BOOMR.window.BOOMR_onload;
	}

	(function() {
		var make_logger;

		if (typeof console === "object" && console.log !== undefined) {
			boomr.log = function(m, l, s) { console.log(s + ": [" + l + "] " + m); };
		}

		make_logger = function(l) {
			return function(m, s) {
				this.log(m, l, "boomerang" + (s?"."+s:""));
				return this;
			};
		};

		boomr.debug = make_logger("debug");
		boomr.info = make_logger("info");
		boomr.warn = make_logger("warn");
		boomr.error = make_logger("error");
	}());


	(function() {
		var ident;
		for (ident in boomr) {
			if (boomr.hasOwnProperty(ident)) {
				BOOMR[ident] = boomr[ident];
			}
		}
		if (!BOOMR.xhr_excludes) {
			//! URLs to exclude from automatic XHR instrumentation
			BOOMR.xhr_excludes={};
		}
	}());

	dispatchEvent("onBoomerangLoaded", { "BOOMR": BOOMR }, true );

}(window));

// end of boomerang beaconing section
;
/*
 * Copyright (c) 2011, Yahoo! Inc.  All rights reserved.
 * Copyright (c) 2012, Log-Normal, Inc.  All rights reserved.
 * Copyrights licensed under the BSD License. See the accompanying LICENSE.txt file for terms.
 */

// This is the Round Trip Time plugin.  Abbreviated to RT
// the parameter is the window
(function(w) {

/*eslint no-underscore-dangle:0*/

	var d=w.document, impl;

	BOOMR = BOOMR || {};
	BOOMR.plugins = BOOMR.plugins || {};
	if (BOOMR.plugins.RT) {
		return;
	}

	// private object
	impl = {
		onloadfired: false,	//! Set when the page_ready event fires
					//  Use this to determine if unload fires before onload
		unloadfired: false,	//! Set when the first unload event fires
					//  Use this to make sure we don't beacon twice for beforeunload and unload
		visiblefired: false,	//! Set when page becomes visible (Chrome/IE)
					//  Use this to determine if user bailed without opening the tab
		initialized: false,	//! Set when init has completed to prevent double initialization
		complete: false,	//! Set when this plugin has completed

		timers: {},		//! Custom timers that the developer can use
					// Format for each timer is { start: XXX, end: YYY, delta: YYY-XXX }
		cookie: "RT",		//! Name of the cookie that stores the start time and referrer
		cookie_exp: 600,	//! Cookie expiry in seconds
		strict_referrer: true,	//! By default, don't beacon if referrers don't match.
					// If set to false, beacon both referrer values and let
					// the back end decide

		navigationType: 0,	// Navigation Type from the NavTiming API.  We mainly care if this was BACK_FORWARD
					// since cookie time will be incorrect in that case
		navigationStart: undefined,
		responseStart: undefined,
		t_start: undefined,	// t_start that came off the cookie
		cached_t_start: undefined,	// cached value of t_start once we know its real value
		t_fb_approx: undefined,	// approximate first byte time for browsers that don't support navtiming
		r: undefined,		// referrer from the cookie
		r2: undefined,		// referrer from document.referer

		// These timers are added directly as beacon variables
		basic_timers: { t_done: 1, t_resp: 1, t_page: 1},

		// Vars that were added to the beacon that we can remove after beaconing
		addedVars: [],

		/**
		 * Merge new cookie `params` onto current cookie, and set `timer` param on cookie to current timestamp
		 * @param params object containing keys & values to merge onto current cookie.  A value of `undefined`
		 *		 will remove the key from the cookie
		 * @param timer  string key name that will be set to the current timestamp on the cookie
		 *
		 * @returns true if the cookie was updated, false if the cookie could not be set for any reason
		 */
		updateCookie: function(params, timer) {
			var t_end, t_start, subcookies, k;

			// Disable use of RT cookie by setting its name to a falsy value
			if (!this.cookie) {
				return false;
			}

			subcookies = BOOMR.utils.getSubCookies(BOOMR.utils.getCookie(this.cookie)) || {};

			if (typeof params === "object") {
				for (k in params) {
					if (params.hasOwnProperty(k)) {
						if (params[k] === undefined ) {
							if (subcookies.hasOwnProperty(k)) {
								delete subcookies[k];
							}
						}
						else {
							if (k==="nu" || k==="r") {
								params[k] = BOOMR.utils.hashQueryString(params[k], true);
							}

							subcookies[k] = params[k];
						}
					}
				}
			}

			t_start = BOOMR.now();

			if (timer) {
				subcookies[timer] = t_start;
			}

			BOOMR.debug("Setting cookie (timer=" + timer + ")\n" + BOOMR.utils.objectToString(subcookies), "rt");
			if (!BOOMR.utils.setCookie(this.cookie, subcookies, this.cookie_exp)) {
				BOOMR.error("cannot set start cookie", "rt");
				return false;
			}

			t_end = BOOMR.now();
			if (t_end - t_start > 50) {
				// It took > 50ms to set the cookie
				// The user Most likely has cookie prompting turned on so
				// t_start won't be the actual unload time
				// We bail at this point since we can't reliably tell t_done
				BOOMR.utils.removeCookie(this.cookie);

				// at some point we may want to log this info on the server side
				BOOMR.error("took more than 50ms to set cookie... aborting: "
						+ t_start + " -> " + t_end, "rt");
			}

			return true;
		},

		/**
		 * Read initial values from cookie and clear out cookie values it cares about after reading.
		 * This makes sure that other pages (eg: loaded in new tabs) do not get an invalid cookie time.
		 * This method should only be called from init, and may be called more than once.
		 *
		 * Request start time is the greater of last page beforeunload or last click time
		 * If start time came from a click, we check that the clicked URL matches the current URL
		 * If it came from a beforeunload, we check that cookie referrer matches document.referrer
		 *
		 * If we had a pageHide time or unload time, we use that as a proxy for first byte on non-navtiming
		 * browsers.
		 */
		initFromCookie: function() {
			var url, subcookies;
			subcookies = BOOMR.utils.getSubCookies(BOOMR.utils.getCookie(this.cookie));

			if (!subcookies) {
				return;
			}

			subcookies.s = Math.max(+subcookies.ld||0, Math.max(+subcookies.ul||0, +subcookies.cl||0));

			BOOMR.debug("Read from cookie " + BOOMR.utils.objectToString(subcookies), "rt");

			// If we have a start time, and either a referrer, or a clicked on URL,
			// we check if the start time is usable
			if (subcookies.s && (subcookies.r || subcookies.nu)) {
				this.r = subcookies.r;
				url = BOOMR.utils.hashQueryString(d.URL, true);

				// Either the URL of the page setting the cookie needs to match document.referrer
				BOOMR.debug(this.r + " =?= " + this.r2, "rt");

				// Or the start timer was no more than 15ms after a click or form submit
				// and the URL clicked or submitted to matches the current page's URL
				// (note the start timer may be later than click if both click and beforeunload fired
				// on the previous page)
				BOOMR.debug(subcookies.s + " <? " + (+subcookies.cl+15), "rt");
				BOOMR.debug(subcookies.nu + " =?= " + url, "rt");

				if (!this.strict_referrer ||
					(subcookies.nu && subcookies.nu === url && subcookies.s < +subcookies.cl + 15) ||
					(subcookies.s === +subcookies.ul && this.r === this.r2)
				) {
					this.t_start = subcookies.s;

					// additionally, if we have a pagehide, or unload event, that's a proxy
					// for the first byte of the current page, so use that wisely
					if (+subcookies.hd > subcookies.s) {
						this.t_fb_approx = parseInt(subcookies.hd, 10);
					}
				}
				else {
					this.t_start = this.t_fb_approx = undefined;
				}
			}

			// Now that we've pulled out the timers, we'll clear them so they don't pollute future calls
			this.updateCookie({
				s: undefined,	// start timer
				r: undefined,	// referrer
				nu: undefined,	// clicked url
				ul: undefined,	// onbeforeunload time
				cl: undefined,	// onclick time
				hd: undefined	// onunload or onpagehide time
			});
		},

		/**
		 * Figure out how long boomerang and config.js took to load using resource timing if available, or built in timestamps
		 */
		getBoomerangTimings: function() {
			var res, urls, url, startTime, data;

			function trimTiming(time, st) {
				// strip from microseconds to milliseconds only
				var timeMs = Math.round(time ? time : 0),
				    startTimeMs = Math.round(st ? st : 0);

				timeMs = (timeMs === 0 ? 0 : (timeMs - startTimeMs));

				return timeMs ? timeMs : "";
			}

			if (BOOMR.t_start) {
				// How long does it take Boomerang to load up and execute (fb to lb)?
				BOOMR.plugins.RT.startTimer("boomerang", BOOMR.t_start);
				BOOMR.plugins.RT.endTimer("boomerang", BOOMR.t_end);	// t_end === null defaults to current time

				// How long did it take from page request to boomerang fb?
				BOOMR.plugins.RT.endTimer("boomr_fb", BOOMR.t_start);

				if (BOOMR.t_lstart) {
					// when did the boomerang loader start loading boomerang on the page?
					BOOMR.plugins.RT.endTimer("boomr_ld", BOOMR.t_lstart);
					// What was the network latency for boomerang (request to first byte)?
					BOOMR.plugins.RT.setTimer("boomr_lat", BOOMR.t_start - BOOMR.t_lstart);
				}
			}

			// use window and not w because we want the inner iframe
			try {
				if (window.performance && window.performance.getEntriesByName) {
					urls = { "rt.bmr": BOOMR.url };

					for (url in urls) {
						if (urls.hasOwnProperty(url) && urls[url]) {
							res = window.performance.getEntriesByName(urls[url]);
							if (!res || res.length === 0) {
								continue;
							}
							res = res[0];

							startTime = trimTiming(res.startTime, 0);
							data = [
								startTime,
								trimTiming(res.responseEnd, startTime),
								trimTiming(res.responseStart, startTime),
								trimTiming(res.requestStart, startTime),
								trimTiming(res.connectEnd, startTime),
								trimTiming(res.secureConnectionStart, startTime),
								trimTiming(res.connectStart, startTime),
								trimTiming(res.domainLookupEnd, startTime),
								trimTiming(res.domainLookupStart, startTime),
								trimTiming(res.redirectEnd, startTime),
								trimTiming(res.redirectStart, startTime)
							].join(",").replace(/,+$/, "");

							BOOMR.addVar(url, data);
							impl.addedVars.push(url);
						}
					}
				}
			}
			catch(e) {
				BOOMR.addError(e, "rt.getBoomerangTimings");
			}
		},

		/**
		 * Check if we're in a prerender state, and if we are, set additional timers.
		 * In Chrome/IE, a prerender state is when a page is completely rendered in an in-memory buffer, before
		 * a user requests that page.  We do not beacon at this point because the user has not shown intent
		 * to view the page.  If the user opens the page, the visibility state changes to visible, and we
		 * fire the beacon at that point, including any timing details for prerendering.
		 *
		 * Sets the `t_load` timer to the actual value of page load time (request initiated by browser to onload)
		 *
		 * @returns true if this is a prerender state, false if not (or not supported)
		 */
		checkPreRender: function() {
			if (BOOMR.visibilityState() !== "prerender") {
				return false;
			}

			// This means that onload fired through a pre-render.  We'll capture this
			// time, but wait for t_done until after the page has become either visible
			// or hidden (ie, it moved out of the pre-render state)
			// http://code.google.com/chrome/whitepapers/pagevisibility.html
			// http://www.w3.org/TR/2011/WD-page-visibility-20110602/
			// http://code.google.com/chrome/whitepapers/prerender.html

			BOOMR.plugins.RT.startTimer("t_load", this.navigationStart);
			BOOMR.plugins.RT.endTimer("t_load");					// this will measure actual onload time for a prerendered page
			BOOMR.plugins.RT.startTimer("t_prerender", this.navigationStart);
			BOOMR.plugins.RT.startTimer("t_postrender");				// time from prerender to visible or hidden

			return true;
		},

		/**
		 * Initialise timers from the NavigationTiming API.  This method looks at various sources for
		 * Navigation Timing, and also patches around bugs in various browser implementations.
		 * It sets the beacon parameter `rt.start` to the source of the timer
		 */
		initFromNavTiming: function() {
			var ti, p, source;

			if (this.navigationStart) {
				return;
			}

			// Get start time from WebTiming API see:
			// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html
			// http://blogs.msdn.com/b/ie/archive/2010/06/28/measuring-web-page-performance.aspx
			// http://blog.chromium.org/2010/07/do-you-know-how-slow-your-web-page-is.html
			p = w.performance || w.msPerformance || w.webkitPerformance || w.mozPerformance;

			if (p && p.navigation) {
				this.navigationType = p.navigation.type;
			}

			if (p && p.timing) {
				ti = p.timing;
			}
			else if (w.chrome && w.chrome.csi && w.chrome.csi().startE) {
				// Older versions of chrome also have a timing API that's sort of documented here:
				// http://ecmanaut.blogspot.com/2010/06/google-bom-feature-ms-since-pageload.html
				// source here:
				// http://src.chromium.org/viewvc/chrome/trunk/src/chrome/renderer/loadtimes_extension_bindings.cc?view=markup
				ti = {
					navigationStart: w.chrome.csi().startE
				};
				source = "csi";
			}
			else if (w.gtbExternal && w.gtbExternal.startE()) {
				// The Google Toolbar exposes navigation start time similar to old versions of chrome
				// This would work for any browser that has the google toolbar installed
				ti = {
					navigationStart: w.gtbExternal.startE()
				};
				source = "gtb";
			}

			if (ti) {
				// Always use navigationStart since it falls back to fetchStart (not with redirects)
				// If not set, we leave t_start alone so that timers that depend
				// on it don't get sent back.  Never use requestStart since if
				// the first request fails and the browser retries, it will contain
				// the value for the new request.
				BOOMR.addVar("rt.start", source || "navigation");
				this.navigationStart = ti.navigationStart || ti.fetchStart || undefined;
				this.responseStart = ti.responseStart || undefined;

				// bug in Firefox 7 & 8 https://bugzilla.mozilla.org/show_bug.cgi?id=691547
				if (navigator.userAgent.match(/Firefox\/[78]\./)) {
					this.navigationStart = ti.unloadEventStart || ti.fetchStart || undefined;
				}
			}
			else {
				BOOMR.warn("This browser doesn't support the WebTiming API", "rt");
			}

			return;
		},

		/**
		 * Validate that the time we think is the load time is correct.  This can be wrong if boomerang was loaded
		 * after onload, so in that case, if navigation timing is available, we use that instead.
		 */
		validateLoadTimestamp: function(t_now, data, ename) {


			// beacon with detailed timing information
			if (data && data.timing && data.timing.loadEventEnd) {
				return data.timing.loadEventEnd;
			}
			else if (ename === "xhr" && (!data || data.initiator !== "spa")) {
				// if this is an XHR event, trust the input end "now" timestamp
				return t_now;
			}
			// Boomerang loaded late and...
			else if (BOOMR.loadedLate) {
				// We have navigation timing,
				if (w.performance && w.performance.timing) {
					// and boomerang loaded after onload fired
					if (w.performance.timing.loadEventStart && w.performance.timing.loadEventStart < BOOMR.t_end) {
						return w.performance.timing.loadEventStart;
					}
				}
				// We don't have navigation timing,
				else {
					// So we'll just use the time when boomerang was added to the page
					// Assuming that this means boomerang was added in onload.  If we logged the
					// onload timestamp (via loader snippet), use that first.
					return BOOMR.t_onload || BOOMR.t_lstart || BOOMR.t_start || t_now;
				}
			}

			// default to now
			return t_now;
		},

		/**
		 * Set timers appropriate at page load time.  This method should be called from done() only when
		 * the page_ready event fires.  It sets the following timer values:
		 *		- t_resp:	time from request start to first byte
		 *		- t_page:	time from first byte to load
		 *		- t_postrender	time from prerender state to visible state
		 *		- t_prerender	time from navigation start to visible state
		 *
		 * @param ename  The Event name that initiated this control flow
		 * @param t_done The timestamp when the done() method was called
		 * @param data   Event data passed in from the caller.  For xhr beacons, this may contain detailed timing information
		 *
		 * @returns true if timers were set, false if we're in a prerender state, caller should abort on false.
		 */
		setPageLoadTimers: function(ename, t_done, data) {
			var t_resp_start;

			if (ename !== "xhr") {
				impl.initFromCookie();
				impl.initFromNavTiming();

				if (impl.checkPreRender()) {
					return false;
				}
			}

			if (ename === "xhr") {
				if (data && data.timing) {
					// Use details from xhr object to figure out resp latency and page time
					// t_resp will use the cookie if available or fallback to NavTiming
					t_resp_start = data.timing.responseStart;
				}
			}
			else if (impl.responseStart) {
				// Use NavTiming API to figure out resp latency and page time
				// t_resp will use the cookie if available or fallback to NavTiming
				t_resp_start = impl.responseStart;
			}
			else if (impl.timers.hasOwnProperty("t_page")) {
				// If the dev has already started t_page timer, we can end it now as well
				BOOMR.plugins.RT.endTimer("t_page");
			}
			else if (impl.t_fb_approx) {
				// If we have an approximate first byte time from the cookie, use it
				t_resp_start = impl.t_fb_approx;
			}

			if (t_resp_start) {
				BOOMR.plugins.RT.endTimer("t_resp", t_resp_start);

				if (impl.timers.t_load) {	// t_load is the actual time load completed if using prerender
					BOOMR.plugins.RT.setTimer("t_page", impl.timers.t_load.end - t_resp_start);
				}
				else {
					BOOMR.plugins.RT.setTimer("t_page", t_done - t_resp_start);
				}
			}

			// If a prerender timer was started, we can end it now as well
			if (impl.timers.hasOwnProperty("t_postrender")) {
				BOOMR.plugins.RT.endTimer("t_postrender");
				BOOMR.plugins.RT.endTimer("t_prerender");
			}

			return true;
		},

		/**
		 * Writes a bunch of timestamps onto the beacon that help in request tracing on the server
		 * 	- rt.tstart: The value of t_start that we determined was appropriate
		 *	- rt.cstart: The value of t_start from the cookie if different from rt.tstart
		 *	- rt.bstart: The timestamp when boomerang started
		 *	- rt.blstart:The timestamp when boomerang was added to the host page
		 *	- rt.end:    The timestamp when the t_done timer ended
		 *
		 * @param t_start The value of t_start that we plan to use
		 */
		setSupportingTimestamps: function(t_start) {
			if (t_start) {
				BOOMR.addVar("rt.tstart", t_start);
			}
			if (typeof impl.t_start === "number" && impl.t_start !== t_start) {
				BOOMR.addVar("rt.cstart", impl.t_start);
			}
			BOOMR.addVar("rt.bstart", BOOMR.t_start);
			if (BOOMR.t_lstart) {
				BOOMR.addVar("rt.blstart", BOOMR.t_lstart);
			}
			BOOMR.addVar("rt.end", impl.timers.t_done.end);	// don't just use t_done because dev may have called endTimer before we did
		},

		/**
		 * Determines the best value to use for t_start.
		 * If called from an xhr call, then use the start time for that call
		 * Else, If we have navigation timing, use that
		 * Else, If we have a cookie time, and this isn't the result of a BACK button, use the cookie time
		 * Else, if we have a cached timestamp from an earlier call, use that
		 * Else, give up
		 *
		 * @param ename	The event name that resulted in this call. Special consideration for "xhr"
		 * @param data  Data passed in from the event caller. If the event name is "xhr",
		 *              this should contain the page group name for the xhr call in an attribute called `name`
		 *		and optionally, detailed timing information in a sub-object called `timing`
		 *              and resource information in a sub-object called `resource`
		 *
		 * @returns the determined value of t_start or undefined if unknown
		 */
		determineTStart: function(ename, data) {
			var t_start;
			if (ename==="xhr") {
				if (data && data.name && impl.timers[data.name]) {
					// For xhr timers, t_start is stored in impl.timers.xhr_{page group name}
					t_start = impl.timers[data.name].start;
				}
				else if (data && data.timing && data.timing.requestStart) {
					// For automatically instrumented xhr timers, we have detailed timing information
					t_start = data.timing.requestStart;
				}
				if (typeof t_start === "undefined" && data && data.initiator === "spa") {
					// if we don't have a start time, set to none so it can possibly be fixed up
					BOOMR.addVar("rt.start", "none");
				}
				else {
					BOOMR.addVar("rt.start", "manual");
				}
			}
			else if (impl.navigationStart) {
				t_start = impl.navigationStart;
			}
			else if (impl.t_start && impl.navigationType !== 2) {
				t_start = impl.t_start;			// 2 is TYPE_BACK_FORWARD but the constant may not be defined across browsers
				BOOMR.addVar("rt.start", "cookie");	// if the user hit the back button, referrer will match, and cookie will match
			}						// but will have time of previous page start, so t_done will be wrong
			else if (impl.cached_t_start) {
				t_start = impl.cached_t_start;
			}
			else {
				BOOMR.addVar("rt.start", "none");
				t_start = undefined;			// force all timers to NaN state
			}

			BOOMR.debug("Got start time: " + t_start, "rt");
			impl.cached_t_start = t_start;

			return t_start;
		},

		page_ready: function() {
			// we need onloadfired because it's possible to reset "impl.complete"
			// if you're measuring multiple xhr loads, but not possible to reset
			// impl.onloadfired
			this.onloadfired = true;
		},

		check_visibility: function() {
			// we care if the page became visible at some point
			if (BOOMR.visibilityState() === "visible") {
				impl.visiblefired = true;
			}

			if (impl.visibilityState === "prerender" && BOOMR.visibilityState() !== "prerender") {
				BOOMR.plugins.RT.done(null, "visible");
			}

			impl.visibilityState = BOOMR.visibilityState();
		},

		page_unload: function(edata) {
			BOOMR.debug("Unload called with " + BOOMR.utils.objectToString(edata) + " when unloadfired = " + this.unloadfired, "rt");
			if (!this.unloadfired) {
				// run done on abort or on page_unload to measure session length
				BOOMR.plugins.RT.done(edata, "unload");
			}

			// set cookie for next page
			// We use document.URL instead of location.href because of a bug in safari 4
			// where location.href is URL decoded
			this.updateCookie({ "r": d.URL }, edata.type === "beforeunload"?"ul":"hd");

			this.unloadfired = true;
		},

		_iterable_click: function(name, element, etarget, value_cb) {
			var value;
			if (!etarget) {
				return;
			}
			BOOMR.debug(name + " called with " + etarget.nodeName, "rt");
			while (etarget && etarget.nodeName.toUpperCase() !== element) {
				etarget = etarget.parentNode;
			}
			if (etarget && etarget.nodeName.toUpperCase() === element) {
				BOOMR.debug("passing through", "rt");

				// user event, they may be going to another page
				// if this page is being opened in a different tab, then
				// our unload handler won't fire, so we need to set our
				// cookie on click or submit
				value = value_cb(etarget);
				this.updateCookie({ "nu": value }, "cl" );
				BOOMR.addVar("nu", BOOMR.utils.cleanupURL(value));
				impl.addedVars.push("nu");
			}
		},

		onclick: function(etarget) {
			impl._iterable_click("Click", "A", etarget, function(t) { return t.href; });
		},

		onsubmit: function(etarget) {
			impl._iterable_click("Submit", "FORM", etarget, function(t) {
				var v = t.getAttribute("action") || d.URL || "";
				return v.match(/\?/) ? v : v + "?";
			});
		},

		domloaded: function() {
			BOOMR.plugins.RT.endTimer("t_domloaded");
		},

		clear: function() {
			if (impl.addedVars && impl.addedVars.length > 0) {
				BOOMR.removeVar(impl.addedVars);
				impl.addedVars = [];
			}
		}
	};

	BOOMR.plugins.RT = {
		// Methods

		init: function(config) {
			BOOMR.debug("init RT", "rt");
			if (w !== BOOMR.window) {
				w = BOOMR.window;
			}
			d = w.document;

			BOOMR.utils.pluginConfig(impl, config, "RT",
						["cookie", "cookie_exp", "strict_referrer"]);

			// A beacon may be fired automatically on page load or if the page dev fires
			// it manually with their own timers.  It may not always contain a referrer
			// (eg: XHR calls).  We set default values for these cases.
			// This is done before reading from the cookie because the cookie overwrites
			// impl.r
			impl.r = impl.r2 = BOOMR.utils.hashQueryString(d.referrer, true);

			// Now pull out start time information from the cookie
			// We'll do this every time init is called, and every time we call it, it will
			// overwrite values already set (provided there are values to read out)
			impl.initFromCookie();

			// We'll get BoomerangTimings every time init is called because it could also
			// include additional timers which might happen on a subsequent init call.
			impl.getBoomerangTimings();

			// only initialize once.  we still collect config and check/set cookies
			// every time init is called, but we attach event handlers only once
			if (impl.initialized) {
				return this;
			}

			impl.complete = false;
			impl.timers = {};

			impl.check_visibility();

			BOOMR.subscribe("page_ready", impl.page_ready, null, impl);
			BOOMR.subscribe("visibility_changed", impl.check_visibility, null, impl);
			BOOMR.subscribe("page_ready", this.done, "load", this);
			BOOMR.subscribe("xhr_load", this.done, "xhr", this);
			BOOMR.subscribe("dom_loaded", impl.domloaded, null, impl);
			BOOMR.subscribe("page_unload", impl.page_unload, null, impl);
			BOOMR.subscribe("click", impl.onclick, null, impl);
			BOOMR.subscribe("form_submit", impl.onsubmit, null, impl);
			BOOMR.subscribe("before_beacon", this.addTimersToBeacon, "beacon", this);
			BOOMR.subscribe("onbeacon", impl.clear, null, impl);

			impl.initialized = true;
			return this;
		},

		startTimer: function(timer_name, time_value) {
			if (timer_name) {
				if (timer_name === "t_page") {
					this.endTimer("t_resp", time_value);
				}
				impl.timers[timer_name] = {start: (typeof time_value === "number" ? time_value : BOOMR.now())};
			}

			return this;
		},

		endTimer: function(timer_name, time_value) {
			if (timer_name) {
				impl.timers[timer_name] = impl.timers[timer_name] || {};
				if (impl.timers[timer_name].end === undefined) {
					impl.timers[timer_name].end =
							(typeof time_value === "number" ? time_value : BOOMR.now());
				}
			}

			return this;
		},

		setTimer: function(timer_name, time_delta) {
			if (timer_name) {
				impl.timers[timer_name] = { delta: time_delta };
			}

			return this;
		},

		addTimersToBeacon: function(vars, source) {
			var t_name, timer,
			    t_other=[];

			for (t_name in impl.timers) {
				if (impl.timers.hasOwnProperty(t_name)) {
					timer = impl.timers[t_name];

					// if delta is a number, then it was set using setTimer
					// if not, then we have to calculate it using start & end
					if (typeof timer.delta !== "number") {
						if (typeof timer.start !== "number") {
							timer.start = impl.cached_t_start;
						}
						timer.delta = timer.end - timer.start;
					}

					// If the caller did not set a start time, and if there was no start cookie
					// Or if there was no end time for this timer,
					// then timer.delta will be NaN, in which case we discard it.
					if (isNaN(timer.delta)) {
						continue;
					}

					if (impl.basic_timers.hasOwnProperty(t_name)) {
						BOOMR.addVar(t_name, timer.delta);
						impl.addedVars.push(t_name);
					}
					else {
						t_other.push(t_name + "|" + timer.delta);
					}
				}
			}

			if (t_other.length) {
				BOOMR.addVar("t_other", t_other.join(","));
				impl.addedVars.push("t_other");
			}

			if (source === "beacon") {
				impl.timers = {};
				impl.complete = false;	// reset this state for the next call
			}
		},

		// Called when the page has reached a "usable" state.  This may be when the
		// onload event fires, or it could be at some other moment during/after page
		// load when the page is usable by the user
		done: function(edata, ename) {
			// try/catch just in case edata contains cross-origin data and objectToString throws a security exception
			try {
				BOOMR.debug("Called done with " + BOOMR.utils.objectToString(edata, undefined, 1) + ", " + ename, "rt");
			}
			catch(err) {
				BOOMR.debug("Called done with " + err + ", " + ename, "rt");
			}
			var t_start, t_done, t_now=BOOMR.now(),
			    subresource = false;

			// We may have to rerun if this was a pre-rendered page, so set complete to false, and only set to true when we're done
			impl.complete = false;

			t_done = impl.validateLoadTimestamp(t_now, edata, ename);

			if (ename==="load" || ename==="visible" || ename==="xhr") {
				if (!impl.setPageLoadTimers(ename, t_done, edata)) {
					return this;
				}
			}

			t_start = impl.determineTStart(ename, edata);

			// If the dev has already called endTimer, then this call will do nothing
			// else, it will stop the page load timer
			this.endTimer("t_done", t_done);

			// make sure old variables don't stick around
			BOOMR.removeVar(
				"t_done", "t_page", "t_resp", "t_postrender", "t_prerender", "t_load", "t_other",
				"r", "r2", "rt.tstart", "rt.cstart", "rt.bstart", "rt.end", "rt.subres", "rt.abld",
				"http.errno", "http.method", "xhr.sync"
			);

			impl.setSupportingTimestamps(t_start);

			this.addTimersToBeacon();

			BOOMR.addVar("r", BOOMR.utils.cleanupURL(impl.r));

			if (impl.r2 !== impl.r) {
				BOOMR.addVar("r2", BOOMR.utils.cleanupURL(impl.r2));
			}

			if (ename === "xhr" && edata) {
				if (edata && edata.data) {
					edata = edata.data;
				}
			}

			if (ename === "xhr" && edata) {
				subresource = edata.subresource;

				if (edata.url) {
					BOOMR.addVar("u", BOOMR.utils.cleanupURL(edata.url.replace(/#.*/, "")));
					impl.addedVars.push("u");
				}

				if (edata.status && (edata.status < -1 || edata.status >= 400)) {
					BOOMR.addVar("http.errno", edata.status);
				}

				if (edata.method && edata.method !== "GET") {
					BOOMR.addVar("http.method", edata.method);
				}

				if (edata.headers) {
					BOOMR.addVar("http.hdr", edata.headers);
				}

				if (edata.synchronous) {
					BOOMR.addVar("xhr.sync", 1);
				}

				if (edata.initiator) {
					BOOMR.addVar("http.initiator", edata.initiator);
				}

				impl.addedVars.push("http.errno", "http.method", "http.hdr", "xhr.sync", "http.initiator");
			}

			// This is an explicit subresource
			if (subresource && subresource !== "passive") {
				BOOMR.addVar("rt.subres", 1);
				impl.addedVars.push("rt.subres");
			}

			impl.updateCookie();

			if (ename==="unload") {
				BOOMR.addVar("rt.quit", "");

				if (!impl.onloadfired) {
					BOOMR.addVar("rt.abld", "");
				}

				if (!impl.visiblefired) {
					BOOMR.addVar("rt.ntvu", "");
				}
			}

			impl.complete = true;

			BOOMR.sendBeacon();

			return this;
		},

		is_complete: function() { return impl.complete; },

		navigationStart: function() {
			if (!impl.navigationStart) {
				impl.initFromNavTiming();
			}
			return impl.navigationStart;
		}
	};

}(window));
// End of RT plugin
;
var KBB = KBB || {};

KBB.Device = (function () {
    'use strict';

    var constants = {
        Desktop: 'desktop',
        Tablet: 'tablet',
        Smartphone: 'smartphone',

        Portrait: 'portrait',
        Landscape: 'landscape'
    };

    var isMatchingDevice = function (deviceList) {
        var dataLayer = KBB.Page.getDataLayer();
        if (dataLayer.device.issmartphone) {
            return deviceList.indexOf(constants.Smartphone) !== -1;
        }

        if (dataLayer.device.istablet) {
            if (dataLayer.targetexperience !== 'desktop' && dataLayer.ismobilefriendlypage) {
                return deviceList.indexOf(constants.Tablet) !== -1;
            }
        }

        return deviceList.indexOf(constants.Desktop) !== -1;
    };


    var getOrientation = function () {
        // JavaScript orientation not supported. Work it out.
        if (document.documentElement.clientWidth > document.documentElement.clientHeight) {
            return constants.Landscape;
        }
        else {
            return constants.Portrait;
        }
    };

    var viewportFilter = function (v) {
        return v !== 'device';
    };

    var viewportSort = function (a, b) {
        if (a === b) {
            return 0;
        }

        return parseInt(a.substring(1)) < parseInt(b.substring(1)) ? 1 : -1;
    };

    var hasMapping = function (mapping) {
        var viewport, viewports, i, j;
        for (i = 0; i < mapping.length; i++) {
            if (isMatchingDevice(mapping[i].device)) {

                viewports = Object.keys(mapping[i]);
                viewports = viewports.filter(viewportFilter).sort(viewportSort);

                // if the viewport has no size mappings, the default adSize value will be used
                if (viewports.length === 0) {
                    return true;
                }

                for (j = 0; j < viewports.length; j++) {
                    viewport = parseInt(viewports[j].substring(1));
                    if (viewport <= window.innerWidth) {
                        return mapping[i][viewports[j]].length > 0;
                    }
                }
            }
        }
        return false;
    };

    /**
    * Gets size from the first viewport setting in the device-specific mappings
    * Used for simplified Video Ad tag
    */
    var getVideoMappings = function (mapping) {
        var deviceMap,
            size,
            i;
        for (i = 0; i < mapping.length; i++) {
            deviceMap = mapping[i];
            if (KBB.Device.isMatchingDevice(deviceMap.device)) {
                for (size in deviceMap) {
                    if (size !== 'device') {
                        //simplified ad tags don't have size mappings, so we take the first size
                        return deviceMap[size];
                    }
                }
            }
        }
        return [];
    };

    return {
        Desktop: constants.Desktop,
        Tablet: constants.Tablet,
        Smartphone: constants.Smartphone,

        Portrait: constants.Portrait,
        Landscape: constants.Landscape,

        isMatchingDevice: isMatchingDevice,
        getOrientation: getOrientation,
        hasMapping: hasMapping,
        getVideoMappings: getVideoMappings
    };

})();
;
var KBB = KBB || {};

KBB.Ads = (function () {
    'use strict';
    var gptLoaded = false,
        tempCmd = [],
        _gptNetworkId = '3030',
        _adCount = 0,
        DartSiteSuffix = {
            Production: '.dfp',
            Test: '.test'
        },
        LoadType = {
            AsyncSRA: 'asyncsra',
            AsyncNoSRA: 'asyncnosra'
        },
        AdLoadType = {
            Initial: 0,
            Dynamic: 1,
            Section: 2,
            Video: 3,
            Scroll: 4
        },
        _currentLoadType = LoadType.AsyncNoSRA,
        pageInitialized = false,
        pendingCallbacks = [],
        //page-level targeting
        pageTargeting = {
            'int': '',
            'pg': '',
            'dpg': '',
            'sec': '',
            'dyn': '',
            'vehid': '',
            'md': '',
            'mdlid': '',
            'mcmdlid': '',
            'mm': '',
            'mk': '',
            'dmk': '',
            'mkid': '',
            'mcmkid': '',
            'pl': '',
            'cat': '',
            'subcat': '',
            'cid': '',
            'atmk': '',
            'atmd': '',
            'pr': '',
            'yr': '',
            'zip': '',
            'co': '',
            'sbc': '',
            'dma': '',
            'os': '',
            'v': '',
            'exp': '',
            'mr': '',
            'env': '',
            'tile': '',
            'sz': '',
            'uuid': '',
            'mpgc': '',
            'mpgh': '',
            'mi': '',
            'mpgrl': '',
            'mpgrh': '',
            'mil': '',
            'mih': '',
            'osid': '',
            'tid': '',
            'psid': '',
            'pi': '',
            'pos': '',
            'kbbr': ''
        },
        defaultAdElementDefinition = {
            elementId: null,
            showAdLabel: true,
            showWhyAds: false,
            allowedDeviceList: null,
            isPrintable: false,
            triggerImmediately: true
        };


    var AdEvent = function (type, data, target, definition, adUnit) {
        this.type = type;
        this.data = data;
        this.target = target;
        this.definition = definition;
        this.adUnit = adUnit;
    };

    /**
     * Find an Ad given an element ID.
     *
     * @param elementId {String} The DOM element ID
     * @param adList {Object[]} List of ads to look through
     */
    var findAd = function (elementId, adList) {
        var i;

        for (i = 0; i < adList.length; i++) {
            // This check is basically saying "if the elementID matches or has numbers after it, then its the
            // matching ad.  This is because if you use position, we just append the position # at the end
            // @fixme: This should check to see if there is also a selector so that the number isn't ignored
            if (elementId.match(adList[i].elementId + '[0-9]*$')) {
                var el = document.getElementById(elementId);
                // If there isn't a selector or the element doesnt exist, just assume it matches.
                // Otherwise check if the selector can be found.
                if (!adList[i].selector || !el) {
                    return adList[i];
                } else if ([].indexOf.call(el.parentNode.querySelectorAll(adList[i].selector), el) !== -1) {
                    return adList[i];
                }
            }
        }
        return null;
    };

    /**
     * Utility function that will get a value out of a given object.  If the value is a function, it will execute the function
     * and return the result.  Otherwise it will just return the value
     */
    var getValue = function (fieldName, obj) {
        var dataLayer = KBB.Page.getDataLayer(),
            field = obj[fieldName];
        return typeof field === 'function' ? field(dataLayer) : field;
    };

    var isAdVisible = function (adUnit) {
        var i;
        if (getValue('visible', adUnit)) {
            for (i = 0; i < adUnit.mapping.length; i++) {
                //If its visible AND there is a matching device mapping, then the ad should be displayed
                if (KBB.Device.isMatchingDevice(adUnit.mapping[i].device)) {
                    return true;
                }
            }
        }
        return false;
    };

    var shouldBundleAd = function (adUnit, context) {
        //create ad slots only for ads with AdLodType=initialPageLoad
        //Note: If we are loading by sectoin, do not define all the slots upfront
        //we must take a non-SRA approach
        return getValue('adLoadType', adUnit) === AdLoadType.Initial
            && !context.loadAdsBySection
            // Ensure that they defined the size for this ad for this device (i.e.
            // dont show ad if they didn't define size mappings for Smartphone)
            && isAdVisible(adUnit)
            //If they provide a selector, we dont know how many ads exists
            //so we cannot put the ad as part of the first refresh
            //Also selectors imply the ads are duplicates so we need different
            //correlator values
            && !adUnit.selector
            //we shouldn't bundle ads if they need a new correlator 
            && !adUnit.updateCorrelator
            //Also, if they only have a scope of "section" don't bother firing the ad here
            && (!adUnit.scope || adUnit.scope.indexOf('global') !== -1);
    };

    var showRefreshOnContext = function (adUnit, context) {
        //create ad slots only for ads with AdLodType=initialPageLoad
        //Note: If we are loading by sectoin, do not define all the slots upfront
        //we must take a non-SRA approach
        return getValue('adLoadType', adUnit) === AdLoadType.Initial
            && !context.loadAdsBySection
            // Ensure that they defined the size for this ad for this device (i.e.
            // dont show ad if they didn't define size mappings for Smartphone)
            && isAdVisible(adUnit)
            //Also, if they only have a scope of "section" don't bother firing the ad here
            && (!adUnit.scope || adUnit.scope.indexOf('global') !== -1);
    };

    /**
     * Setup the ads.  Regardless of how we are loading, we will define the initial ads upfront unless we are
     * loading by section.  If we load by section, all ads are treated as dynamic and load as their section
     * comes into view
     *
     * @param adList {Object[]} The list of ad definitions
     * @param loadType {String} Either 'asyncsra' or 'asyncnosra'.
     */
    var setupAds = function (adList, loadType) {
        _currentLoadType = loadType;

        googletag.cmd.push(function () {
            var context = KBB.Page.getContext(),
                sectionsQuery = context.pageSections.map(function (section) { return section.selector; }).join(','),
                i,
                adUnit;

            gptLoaded = true;

            //Once the first ad renders, we can start rendering dynamic ads
            googletag.pubads().addEventListener('slotRenderEnded', function (e) {
                gptLoaded = true;
                for (i = 0; i < tempCmd.length; i++) {
                    googletag.cmd.push(tempCmd[i]);
                }
                tempCmd = [];

                //find the ad in gptAds collection and publish mediator event
                //the event channel is slotRenderEnded:[GptAdElementId], e.g. slotRenderEnded:kbbAdsGlobalOverlay
                var ctx = KBB.Page.getContext();
                if (ctx && ctx.gptAds) {
                    var gptElementIds = Object.keys(ctx.gptAds);
                    for (i = 0; i < gptElementIds.length; i++) {
                        if (ctx.gptAds[gptElementIds[i]].gptAd === e.slot) {
                            checkCallbackList(gptElementIds[i]);

                            //we found a slot for which slotRenderEnded event got triggered
                            var mediatorChannel = Utils.getMediatorChannel(Utils.eventTypes.slotRenderEnded, gptElementIds[i]);
                            Utils.getMediator().publish(mediatorChannel, e);
                            break;
                        }
                    }
                }
            });

            setPageTargeting();

            for (i = 0; i < adList.length; i++) {
                adUnit = adList[i];
                //create ad slots only for ads with AdLodType=initialPageLoad
                //Note: If we are loading by sectoin, do not define all the slots upfront
                //we must take a non-SRA approach
                //Also, if they only have a scope of "section" don't bother firing the ad here
                if (shouldBundleAd(adUnit, context)) {
                    //If we are loading ads by section, we'll need to check if the ad is in a
                    //section before we define it
                    defineGoogleSlot(adUnit);
                    gptLoaded = false;
                }
            }

            //Single Request only functions
            if (_currentLoadType === LoadType.AsyncSRA) {
                googletag.pubads().enableSingleRequest();
            }

            googletag.enableServices();
        });
    };

    /**
     * Handle what should happen if a context is activated and how ads should fire.
     * Assume that the DOM is on the page at this point and non of the ads have fired
     *
     * @param context {Object} The context
     */
    var activateContext = function (context) {

        googletag.cmd.push(function () {
            var adList = [],
                i, adUnit, slot, elements, element;

            setPageTargeting();

            googletag.pubads().updateCorrelator();

            //Context changed, also assume the DOM has been added to the page somehow
            for (i = 0; i < context.ads.length; i++) {
                adUnit = context.ads[i];

                if (showRefreshOnContext(adUnit, context)) {
                    //if the ad slot hasn't been defined yet
                    //create it dynamically and refresh the ad
                    adUnit = context.ads[i];
                    elements = [document.getElementById(adUnit.elementId)];

                    if (adUnit.selector) {
                        //If its a POS ad, then refresh immediately rather than waiting
                        elements = document.querySelectorAll(adUnit.selector);
                    }

                    for (var j = 0; j < elements.length; j++) {
                        element = elements[j];

                        if (element) {
                            slot = context.gptAds[element.id];

                            if (!slot) {
                                slot = defineGoogleSlot(adUnit, element.id);
                                setSlotTargetingValues(slot, new AdEvent('initial', null, element, slot, adUnit));
                                initializeDiv(slot);
                                googletag.display(slot.gptElementId);
                            }
                            else {
                                initializeDiv(slot);
                                if (adUnit.selector) {
                                    googletag.pubads().refresh([slot.gptAd]);
                                }
                                else {
                                    adList.push(slot.gptAd);
                                }
                            }
                        }
                    }
                }
            }
            if (adList.length > 0) {
                googletag.pubads().refresh(adList);
            }
        });
    };

    /**
     * Handle what should happen if a context is deactivated.  Currently just a place holder
     *
     * @param context {Object} The context
     */
    var deactivateContext = function (context, prevContext) {
        setPageTargeting();
    };


    /**
    * Populates page level targeting object
    */
    var populatePageTargeting = function () {
        var dataLayer = KBB.Page.getDataLayer();

        //general values - intent, page, dyn etc.
        pageTargeting['int'] = dataLayer.info.intent ? dataLayer.info.intent.replace(/\-/g, '') : ''; //js compressor breaks on pageTargeting.int
        pageTargeting.pg = dataLayer.omniture.pagename;
        pageTargeting.dpg = dataLayer.omniture.detailpagename;
        pageTargeting.sec = dataLayer.omniture.supersectionname;
        pageTargeting.dyn = dataLayer.ads.dyn;
        pageTargeting.os = dataLayer.nativeapps.experience + '_' + dataLayer.nativeapps.os;
        pageTargeting.v = dataLayer.nativeapps.version;
        pageTargeting.exp = dataLayer.nativeapps.experience + '_' + dataLayer.nativeapps.device;
        pageTargeting.mr = dataLayer.info.mileagerange;
        pageTargeting.env = dataLayer.ads.environment;
        pageTargeting.uuid = dataLayer.ads.uuid;
        pageTargeting.mi = dataLayer.info.mileage;
        pageTargeting.mil = dataLayer.info.mileagerangelow;
        pageTargeting.mih = dataLayer.info.mileagerangehigh;
        pageTargeting.osid = dataLayer.sessionid;
        pageTargeting.psid = dataLayer.paidsearch.paidsearchid.substr(0, 8);
        pageTargeting.pi = dataLayer.pageinstance;
        pageTargeting.pl = dataLayer.ads.pl;

        //location key-values
        pageTargeting.zip = dataLayer.location.zip;
        pageTargeting.co = dataLayer.location.statecounty;
        pageTargeting.sbc = dataLayer.location.statesubcounty;
        pageTargeting.dma = dataLayer.location.dma;

        //vehicle data key-values
        pageTargeting.vehid = dataLayer.info.vehicle.id;
        if (!!(dataLayer.info.model.shortname) || !!(dataLayer.info.manufacturer.shortname)) {
            pageTargeting.md = dataLayer.info.model.shortname + '_' + dataLayer.info.manufacturer.shortname;
        } else {
            pageTargeting.md = '';
        }
        if (dataLayer.info.vehicleClass !== '' && (dataLayer.info.vehicleClass === 'motorcycle' || dataLayer.info.vehicleClass === 'snowmobile' || dataLayer.info.vehicleClass === 'personalwatercraft')) {
            pageTargeting.mcmdlid = dataLayer.info.model.id;
            pageTargeting.mcmkid = dataLayer.info.manufacturer.id;
            pageTargeting.mdlid = '';
            pageTargeting.mkid = '';
        } else {
            pageTargeting.mdlid = dataLayer.info.model.id;
            pageTargeting.mcmdlid = '';
            pageTargeting.mkid = dataLayer.info.manufacturer.id;
            pageTargeting.mcmkid = '';
        }

        pageTargeting.mm = (dataLayer.info.model.shortmarketname !== '' ? dataLayer.info.manufacturer.shortname + '_' + dataLayer.info.model.shortmarketname : '');
        pageTargeting.mk = (dataLayer.info.manufacturer.shortname !== '' ? dataLayer.info.manufacturer.shortname : dataLayer.ads.unknown);
        pageTargeting.dmk = pageTargeting.mk;
        pageTargeting.cat = dataLayer.info.shortcategory;
        pageTargeting.subcat = dataLayer.info.subcategory;
        pageTargeting.cid = dataLayer.ads.cid;
        pageTargeting.atmk = dataLayer.classifiedsinfo.atcmakecode;
        pageTargeting.atmd = dataLayer.classifiedsinfo.atcmodelcode;
        pageTargeting.pr = dataLayer.info.vehicle.price;
        pageTargeting.yr = dataLayer.info.yearid;
        pageTargeting.mpgc = dataLayer.info.vehicle.mpgcity;
        pageTargeting.mpgh = dataLayer.info.vehicle.mpghwy;
        pageTargeting.mpgrl = dataLayer.info.vehicle.mpgrangelow; //was listed as mpgl in legacy key-values, renamed to mpgrl to keep consistent with the mpgrangehigh key
        pageTargeting.mpgrh = dataLayer.info.vehicle.mpgrangehigh; //was listed as mpgh in legacy key-values, overriding the mpg hwy setting
        pageTargeting.ua = encodeURIComponent(navigator.userAgent);
        pageTargeting.kbbr = Utils.isInternalReferrerHostName();
    };

    /**
     * Set page level targeting in GPT library
     */
    var setPageTargeting = function () {
        var field, item;

        //set page targeting properties
        populatePageTargeting();

        //set targeting in GPT
        for (field in pageTargeting) {
            item = pageTargeting[field];
            if (item !== null && item !== '' && item !== undefined) {
                setTargeting(field, item);
            } else {
                removeTargeting(field);
            }
        }
    };

    //set test id when prop39 is defined
    var setTestIds = function () {
        pageTargeting.tid = s.prop39.split('^');
        if (typeof googletag !== 'undefined') {
            googletag.cmd.push(function () {
                setTargeting('tid', pageTargeting.tid);
            });
        }
    };

    //if no adElementId is passed - the targeting is set for the page
    //otherwise the targeting is set for the ad slot
    var setTargeting = function (key, value, adSlot) {

        if (key === undefined || key === null || key === '' || value === undefined || value === null || value === '') {
            return;
        }
        //console.log(_logPrefix + 'Set Targeting ' + (!!adSlot ? 'Slot' : 'Page') + ':' + key.toLowerCase() + ' = ' + value);  // eslint-disable-line no-console
        if (adSlot) {
            //if the page level targeting for the key exists, set targeting only if it's different from the page level
            if (!!pageTargeting[key]) {
                if (pageTargeting[key] !== value) {
                    adSlot.setTargeting(key.toLowerCase(), '' + value);
                }
            } else {
                adSlot.setTargeting(key.toLowerCase(), '' + value);
            }
        } else {
            googletag.pubads().setTargeting(key.toLowerCase(), '' + value);
        }
    };

    //if no adElementId is passed - the targeting is cleared for the page
    //otherwise the targeting is cleared for the ad slot
    var removeTargeting = function (key, adSlot) {
        if (typeof key === 'undefined' || key === null || key === '') {
            return;
        }
        key = key.toLowerCase();
        if (adSlot) {
            adSlot.clearTargeting(key);
        } else {
            var targetingKeys = googletag.pubads().getTargetingKeys();
            if (targetingKeys && targetingKeys.indexOf(key) !== -1) {
                googletag.pubads().clearTargeting(key);
            }
        }
    };

    var sortSize = function (sizeArray) {
        return sizeArray.sort(function (a, b) {
            if (!a) {
                return -1;
            }
            if (!b) {
                return 1;
            }
            if (a[1] === b[1]) {
                return a[0] > b[0] ? 1 : -1;
            }
            return a[1] > b[1] ? 1 : -1;
        });
    };

    /**
     * Populates Ad dart site from configuration
     * Implements dart site override for demo.kbb.com
     */
    var getDartSite = function (adUnit) {
        var dartSite = getValue('dartSite', adUnit);
        // All demo.kbb.com dart sites should end with .test
        if ((window.location.hostname === 'demo.kbb.com') && (typeof dartSite !== 'undefined')) {
            dartSite = dartSite.replace(DartSiteSuffix.Production, DartSiteSuffix.Test);
        }
        return dartSite;
    };

    var getNetworkId = function (adUnit) {
        var networkId = _gptNetworkId,
                        adOrigin;
        //if adOrigin is ATC, use ATC network id
        adOrigin = getValue('adOrigin', adUnit);
        if (adOrigin === 'ATC') {
            var dl = KBB.Page.getDataLayer();
            networkId = dl.ads.classifiedsinlineadnetworkid;
        }
        return networkId;
    };

    var createGoogleSlot = function (adElementId, adUnit) {
        var context = KBB.Page.getContext(),
            adSlot,
            mapping,
            size,
            dartSite,
            adOrigin,
            networkId;

        if (adUnit) {
            if (!context.disableAdMappings && adUnit.mapping && adUnit.mapping.length) {
                for (var i = 0; i < adUnit.mapping.length; i++) {

                    var deviceMap = adUnit.mapping[i];

                    if (KBB.Device.isMatchingDevice(deviceMap.device)) {
                        mapping = googletag.sizeMapping();

                        for (size in deviceMap) {
                            if (size !== 'device') {
                                mapping.addSize([Number(size.substring(1)), 50], sortSize(deviceMap[size]));
                            }
                        }

                        mapping = mapping.build();

                        //Note: i only take the first matching device.  No point in continuing and getting conflicts
                        break;
                    }
                }
            }

            dartSite = getDartSite(adUnit);
            networkId = getNetworkId(adUnit);

            if (getValue('outOfPage', adUnit)) {
                adSlot = googletag.defineOutOfPageSlot('/' + networkId + '/' + dartSite, adElementId);
            } else {
                adSlot = googletag.defineSlot('/' + networkId + '/' + dartSite, sortSize(adUnit.adSize), adElementId);
            }
            if (mapping) {
                adSlot.defineSizeMapping(mapping);
            }
            adSlot.addService(googletag.pubads());

            //set slot-specific targeting
            //sp value
            setTargeting('sp', getValue('sponsorship', adUnit), adSlot);
            //element Id
            setTargeting('elid', adElementId, adSlot);
            return adSlot;
        }
    };

    //create Google ad slot
    var defineGoogleSlot = function (adUnit, elementId) {
        var context = KBB.Page.getContext(),
            adElementId = elementId || adUnit.elementId,
            gptDef = {},
            adSlot;

        if (adUnit && !context.gptAds[adElementId]) {
            gptDef.elementId = adElementId;
            gptDef.gptElementId = 'gptAd' + _adCount;
            gptDef.gptAd = createGoogleSlot(gptDef.gptElementId, adUnit);
            gptDef.adUnit = adUnit;

            _adCount++;

            context.gptAds[adElementId] = gptDef;
            setSlotTargetingValues(adUnit, new AdEvent(null, null, null, gptDef, adUnit));

            return gptDef;
        }
    };



    //displays ad only if the ad slot is already defined (for page load)
    var showAd = function (elementId) {
        var context = KBB.Page.getContext(),
            element = document.getElementById(elementId),
            adUnit = findAd(elementId, context.ads),
            hasMapping = null;

        if (adUnit) {
            if (!pageInitialized) {
                googletag.cmd.push(function () {
                    var adDef = context.gptAds[elementId];
                    if (adDef) {
                        hasMapping = KBB.Device.hasMapping(adDef.adUnit.mapping);
                        if (hasMapping) {
                            initializeDiv(adDef, elementId);
                            setSlotTargetingValues(adUnit, new AdEvent(null, null, element, adDef, adUnit));
                            googletag.display(adDef.gptElementId);
                        }
                    }
                    else {
                        if ((adUnit.selector || adUnit.updateCorrelator) && getValue('adLoadType', adUnit) === AdLoadType.Initial) {
                            //Ads with position or those that require new correlator are treated as separate
                            refreshAd(adUnit, { target: element });
                        }
                    }
                });
            }
        }
    };

    var setAdContainerId = function (adElement, gptElementId) {

        // id element.firstElementChild is undefined (it's not supported in ie8) revert to element child collection
        var innerContainer = (adElement.firstElementChild || adElement.children[0]);
        var gptContainer = (innerContainer.firstElementChild || innerContainer.children[0]);

        gptContainer.id = gptElementId;
    };

    /**
     * Due to the limitation that each element ID can only be defined with 1 dart site, I create an
     * internal ID to work around the limitation
     */
    var initializeDiv = function (adDefinition) {
        var element = document.getElementById(adDefinition.elementId);

        setAdContainerId(element, adDefinition.gptElementId);

        // ensure class name is clear. Closing an ad sets class name to hidden. See clearGptAd
        if (element) {
            var cn = element.className,
                rxp = new RegExp('\\s?\\bad?\\s?hidden\\b', 'g');
            cn = cn.replace(rxp, '');
            element.className = cn;
        }
        //unclear the ad
        adDefinition.isCleared = false;
    };

    var refreshAd = function (adUnit, event) {
        var cmdList = gptLoaded ? googletag.cmd : tempCmd,
            context = KBB.Page.getContext(),
            elementId;

        //make sure the element exists
        if (!adUnit || !event.target) {
            return;
        }

        elementId = event.target.id;

        cmdList.push(function () {
            var adDef = context.gptAds[elementId];

            if (isAdVisible(adUnit)) {
                if (adDef) {
                    initializeDiv(adDef);
                    setSlotTargetingValues(adUnit, event);
                    googletag.pubads().clear([adDef.gptAd]);
                    googletag.pubads().refresh([adDef.gptAd]);
                }
                else {
                    adDef = event.definition = defineGoogleSlot(adUnit, elementId);
                    initializeDiv(adDef);
                    setSlotTargetingValues(adUnit, event);
                    //display the ad
                    //console.log(_logPrefix + 'Ad Slot Defined Dynamically ' + adDef.elementId);  // eslint-disable-line no-console
                    googletag.display(adDef.gptElementId);
                }
            }
        });
    };

    // clearGptAd
    // clears a gpt ad
    // removes all child nodes of the ad, also removes gptid
    // sets ad div to hidden
    var clearGptAd = function (adUnit, event) {
        var gptTagDiv,
            gptIdDiv,
            gptAd,
            context = KBB.Page.getContext();

        if (!adUnit) {
            return;
        }

        gptTagDiv = document.getElementById(adUnit.elementId); //e.g. div with id=kbbAdsSlpLeaderboard

        if (gptTagDiv) {
            gptIdDiv = gptTagDiv.querySelector('.gpt-ad'); //e.g. div id=gptAd0
            if (gptIdDiv && gptIdDiv.hasChildNodes()) {
                gptIdDiv.innerHTML = '';
            }
            gptTagDiv.className = 'ad hidden';
        }

        //mark the ad cleared so that it's not refreshed with inline refreshes
        if (context && context.gptAds) {
            gptAd = context.gptAds[adUnit.elementId];
            if (gptAd) {
                gptAd.isCleared = true;
            }
        }
    };

    // add targeting values to adunit
    // adUnit: the adUnit to add targeting to
    // adTargetingValues: the adTargetingValues key/value object
    var setSlotTargetingValues = function (adUnit, event) {
        var adTargetingValues = {},
            field, item;

        //if needed - update the correlator
        if (adUnit.updateCorrelator) {
            googletag.pubads().updateCorrelator();
        }

        if (event.target && event.target.getAttribute('data-ad-position')) {
            setTargeting('pos', event.target.getAttribute('data-ad-position'), event.definition.gptAd);
        }

        if (typeof event === 'undefined' || !adUnit.setup) {
            return;
        }

        //populate ad tageting values from event
        //this function is defined in ad configuration
        adUnit.setup(adTargetingValues, event);

        //iterate through a slot targeting properties
        for (field in adTargetingValues) {
            item = adTargetingValues[field];
            if (item !== null && item !== '' && item !== undefined) {
                setTargeting(field, item, event.definition.gptAd);
            }
            else {
                //If the field exists in slot targeting but is blank or null, that
                //means we want to clear the existing data
                event.definition.gptAd.setTargeting(field.toLowerCase(), '');
            }
        }
        setTargeting('sp', getValue('sponsorship', adUnit), event.definition.gptAd);
    };

    //refresh multiple ads 
    var refresh = function () {
        var context = KBB.Page.getContext(),
            selectorAds = [],
            adUnit,
            adsToRefresh = [],
            refreshed = [],
            i,
            adId,
            adDef;

        for (adId in context.gptAds) {
            adDef = context.gptAds[adId];
            adUnit = adDef.adUnit;

            if (getValue('adLoadType', adUnit) === AdLoadType.Initial) {
                //refresh only initial load ads
                //selector ads and ads that update correlator need to fire one-by-one
                if (adUnit.selector || adUnit.updateCorrelator) {
                    selectorAds.push(adDef);
                }
                //other ads can be bundled
                else {
                    adsToRefresh.push(adDef.gptAd);
                }
                refreshed.push(adDef.gptElementId);
                $('#' + adDef.elementId).removeClass('hidden');
            }
            //refresh triggered ads that haven't been cleared
            else if (adUnit.trigger && !adDef.isCleared) {
                //ads with updated correlator need to fire one-by-one
                if (adUnit.updateCorrelator) {
                    selectorAds.push(adDef);
                }
                else {
                    adsToRefresh.push(adDef.gptAd);
                }
                refreshed.push(adDef.gptElementId);
                $('#' + adDef.elementId).removeClass('hidden');
            }
        }

        //refresh multiple ads in one call
        googletag.cmd.push(function () {
            setPageTargeting();

            if (adsToRefresh.length > 0) {
                //console.log(_logPrefix + 'Ads Refreshed ' + refreshed.join(','));  // eslint-disable-line no-console
                //clearing ad creative before refreshes resolves issues with studio ad creatives breaking after multiple inline refreshes

                googletag.pubads().clear(adsToRefresh);
                googletag.pubads().refresh(adsToRefresh);
            }

            if (selectorAds.length > 0) {
                for (i = 0; i < selectorAds.length; i++) {
                    googletag.pubads().clear([selectorAds[i].gptAd]);
                    googletag.pubads().refresh([selectorAds[i].gptAd]);
                }
            }
        });
    };

    var trigger = function (context, triggerEvent, data) {
        var ad, i, ads, j;
        context = KBB.Page.getContext();

        if (triggerEvent) {
            for (i = 0; i < context.ads.length; i++) {
                ad = context.ads[i];
                if (Utils.eventMatches(ad.trigger, triggerEvent)) {
                    if (ad.selector) {
                        ads = document.querySelectorAll(ad.selector);
                        for (j = 0; j < ads.length; j++) {
                            refreshAd(ad, new AdEvent(triggerEvent, data, ads[j], context.gptAds[ads[j].id], ad));
                        }
                    }
                    else {
                        refreshAd(ad, new AdEvent(triggerEvent, data, document.getElementById(ad.elementId), context.gptAds[ad.elementId], ad));
                    }
                }
                else if (Utils.eventMatches(ad.triggerClear, triggerEvent)) {
                    clearGptAd(ad, new AdEvent(triggerEvent, data));
                }
            }
        }
    };


    var refreshScrollAds = function (context) {
        var ad, i, j, adList = [], element, elements;

        for (i = 0; i < context.ads.length; i++) {
            ad = context.ads[i];

            if (getValue('adLoadType', ad) === AdLoadType.Scroll) {
                if (ad.selector) {
                    elements = document.querySelectorAll(ad.selector);
                    for (j = 0; j < elements.length; j++) {
                        if (Utils.elementInViewport(elements[j])) {
                            refreshAd(ad, new AdEvent('scroll', null, elements[j]));
                        }
                    }
                }
                else {
                    element = document.getElementById(ad.elementId);
                    if (Utils.elementInViewport(element)) {
                        refreshAd(ad, new AdEvent('scroll', null, element));
                    }
                }
            }
        }

    };

    // used only in desktop (kbb.desktop.bottom.js)
    var setupListeners = function () {
        pageInitialized = true;
        var resizeHistory = Utils.getResizeAdHistory();

        if (resizeHistory.length >= 0) {
            for (var adMessage in resizeHistory) {
                var resizeAd = KBB.Ads.resizeAd(resizeHistory[adMessage]);
                Utils.getMediator().subscribe(Utils.eventTypes.resizeAd, resizeAd);
            }
        }
        Utils.getMediator().subscribe(Utils.eventTypes.resizeAd, KBB.Ads.resizeAd);
    };

    var checkCallbackList = function (elementId) {
        var i;

        for (i = 0; i < pendingCallbacks.length; i++) {
            if (checkCallback(pendingCallbacks[i], elementId)) {
                pendingCallbacks.splice(i, 1);
                i--;
            }
        }
    };

    var checkCallback = function (callback, elementId) {
        var j;

        if (elementId) {
            for (j = 0; j < callback.adList.length; j++) {
                if (callback.adList[j] === elementId) {
                    callback.adList.splice(j, 1);
                    j--;
                }
            }
        }

        if (!callback.adList.length) {
            callback.callback();
            return true;
        }

        return false;
    };

    /**
     * Refresh the ads in a given section.
     */
    var refreshSection = function (section, isFirstView) {
        var context = KBB.Page.getContext(),
            $sectionEl,
            pendingCallback = {
                callback: function () {
                    KBB.Page.trigger('sectionViewComplete', section);
                },
                adList: []
            },
            i, ad;

        pendingCallbacks.push(pendingCallback);

        if (section.group) {
            $sectionEl = $('[data-section-index]').filter(function () {
                return KBB.Page.getSectionGroup(this, context) === section.group;
            });
        }
        else {
            $sectionEl = $(section.el);
        }

        for (i = 0; i < context.ads.length; i++) {
            ad = context.ads[i];
            if (!isFirstView || (ad.scope && ad.scope.indexOf('global') === -1)) {
                //On the first section view, ignore any global ads because we would have already
                //fired the ad.
                if (ad.scope && ad.scope.indexOf('section') !== -1) {
                    if (ad.selector) {
                        $sectionEl.find(ad.selector).each(function () {
                            pendingCallback.adList.push(this.id);
                            refreshAd(ad, new AdEvent(null, null, this, context.gptAds[this.id], ad));
                        });
                    }
                    else {
                        $sectionEl.find('#' + ad.elementId).each(function () {
                            pendingCallback.adList.push(this.id);
                            refreshAd(ad, new AdEvent(null, null, this, context.gptAds[this.id], ad));
                        });
                    }
                }
            }
        }

        //If we didn't load any ads just call the callback!
        if (checkCallback(pendingCallback)) {
            pendingCallbacks.splice(pendingCallbacks.length - 1, 1);
        }
        else {
            setTimeout(function () {
                //If the ads dont finish loading in 2 seconds, just proceed so we dont get held up
                var callbackIndex = pendingCallbacks.indexOf(pendingCallback);
                if (pendingCallback.adList.length > 0 && callbackIndex >= 0) {
                    pendingCallbacks.splice(callbackIndex, 1);
                    pendingCallback.callback();
                }

            }, 2000);
        }
    };

    var hasParent = function (element, parentId) {
        //Check all the parents to see if any match the given element ID
        while (element.parent) {
            if (element.parent.id === parentId) {
                return true;
            }
            element = element.parent;
        }
        return false;
    };

    var resizeAd = function (msgData) {
        var iframe, ad;
        ad = document.getElementById(msgData.adUniqueId);
        if (ad) {
            iframe = ad.querySelectorAll('iframe')[0];
            if (iframe) {
                iframe.height = msgData.height;
                iframe.width = msgData.width;
            }
        }
    };

    /**
    * Concatenates params with & or encoded &
    */
    var concatenateSimplifiedAdParameters = function (params, encode) {
        var encEqual = '%3D', // encoding for =
            encAmp = '%26', // encoding for &
            encComma = '%2C', // encoding for ,
            field = '',
            item = '',
            idx = -1,
            charToTrim = '',
            result = '';
        for (field in params) {
            item = params[field];
            if (item !== null && item !== '' && typeof item !== 'undefined') {
                //array items are separated by commas
                if (Array.isArray(item)) {
                    item = item.join(',');
                }
                if (encode) {
                    result += field + encEqual + (item + '').replace(/,/g, encComma) + encAmp;
                } else {
                    result += field + '=' + item + '&';
                }
            }
        }
        //strip off the last & (or encoded &)
        charToTrim = encode ? encAmp : '&';
        idx = result.lastIndexOf(charToTrim);
        if (idx !== -1 && idx === (result.length - charToTrim.length)) {
            result = result.substring(0, idx);
        }
        return result;
    };

    /**
    * Creates Simplified GPT Ad Url for Video Ads
    */
    var getVideoAdUrl = function (elementId, playerId, videoIndex) {
        var videoAdsServerHost = 'https://pubads.g.doubleclick.net/gampad/ads',
            url = location.protocol + (location.port === '' ? '' : ':' + location.port) + '//' + location.hostname + location.pathname,
            videoParams = {
                'iu': '', //ad configuration item
                'sz': '', //ad configuration item
                'env': 'vp',
                'impl': 's',
                'gdfp_req': 1,
                'unviewed_position_start': 1,
                'output': '', //ad configuration item
                'correlator': playerId ? '{timestamp}' : Date.now(),
                'url': url,
                'description_url': encodeURIComponent(url),
                'ciu_szs': '' //ad configuration item
            },
            videoSlotTargeting = {
                'sp': '',
                'bcvid': '',
                'plid': '',
                'vindex': videoIndex > 0 ? videoIndex : 1
            },
            context = KBB.Page.getContext(),
            adUnit = findAd(elementId, context.ads),
            size,
            dartSite,
            sponsorship,
            dfpAdUrl = '';

        if (adUnit && getValue('adLoadType', adUnit) === AdLoadType.Video && isAdVisible(adUnit)) {
            //in case the video ad tag is the first thing that runs on the page
            populatePageTargeting();

            //populate video targeting parameters
            //get the first viewport setting in the device-specific mappings
            if (!context.disableAdMappings && adUnit.mapping && adUnit.mapping.length) {
                size = KBB.Device.getVideoMappings(adUnit.mapping);
            } else {
                //otherwise take the ad size value
                size = adUnit.adSize;
            }
            videoParams.sz = sortSize(size).map(function(v) {
                return v.join('x');
            }).join('|');

            dartSite = getDartSite(adUnit);
            videoParams.iu = '/' + _gptNetworkId + '/' + dartSite;
            videoParams.output = adUnit.output;

            if (adUnit.companionAdSize) {
                videoParams.ciu_szs = adUnit.companionAdSize.map(function (v) { return v.join('x'); }).join(','); // eslint-disable-line
            }

            //populate slot-level targeting parameters
            sponsorship = getValue('sponsorship', adUnit);
            if (sponsorship > 0) {
                videoSlotTargeting.sp = sponsorship;
            }

            //populate video ID
            if (playerId) {
                videoSlotTargeting.bcvid = '{mediainfo.id}';
                videoSlotTargeting.plid = playerId;
            }

            // generate the url
            dfpAdUrl = videoAdsServerHost + '?' +
                // required parameters
                concatenateSimplifiedAdParameters(videoParams, false) +
                // optional parameters
                '&scp=' + concatenateSimplifiedAdParameters(videoSlotTargeting, true) +
                '&cust_params=' + concatenateSimplifiedAdParameters(pageTargeting, true);
        }

        return dfpAdUrl;
    };

    var isLowerFunnelPage = function () {
        //when vehicle make and model are known.
        var dl = KBB.Page.getDataLayer();
        if (dl && (dl.info.model.id !== '')) {
            return true;
        }
        return false;
    };

    var isKnownCategoryPage = function () {
        //when the subcategory (segment) has value
        var dl = KBB.Page.getDataLayer();
        if (dl && dl.info.subcategory !== 'unk' && dl.info.subcategory !== '') {
            return true;
        }
        return false;
    };

    /**
     * Adds HTML element for an ad
     * Client-side implementation of RenderGptAd extension
     * Warning: This method has to be updated along with any changes to the RenderGptAd extension
     */
    var renderGptAdHtmlElement = function (adElementDefinition) {
        var adElement;

        if (!adElementDefinition || !adElementDefinition.elementId) {
            return false;
        }
        adElementDefinition = Utils.extend(defaultAdElementDefinition, adElementDefinition);

        //check for device if it's defined
        if (adElementDefinition.allowedDeviceList && adElementDefinition.allowedDeviceList.length > 0) {
            if (!(KBB.Device.isMatchingDevice(adElementDefinition.allowedDeviceList))) {
                return false;
            }
        }

        adElement = document.getElementById(adElementDefinition.elementId);
        if (adElement) {
            adElement.innerHTML = '<div class="ad-inner-container"><div class="gpt-ad"></div>'
                + (adElementDefinition.showAdLabel ? '<div class="ad-label">Advertisement</div>' : '')
                + (adElementDefinition.showWhyAds ? '<div class="why-ads">Why Ads?</div>' : '')
                + '</div>';
            return true;
        }
        return false;
    };

    /**
     * Renders Dynamic Ad
     * Runs after initial load ads already fired
     */
    var renderDynamicAd = function (adDefinition, adElementDefinition, contextNameOrList) {
        var list = [], adElementTrigger;

        if (!adDefinition || !adDefinition.elementId) {
            return false;
        }

        //'root' by default
        contextNameOrList = contextNameOrList || 'root';
        //prepend ad.trigger to the element ID
        adElementTrigger = 'ad.trigger.' + adDefinition.elementId;

        //initialize ad definition values
        adDefinition.adLoadType = KBB.Ads.AdLoadType.Dynamic;
        adDefinition.outOfPage = (typeof adDefinition.outOfPage === 'undefined' ? false : adDefinition.outOfPage);
        adDefinition.visible = (typeof adDefinition.visible === 'undefined' ? true : adDefinition.visible);
        adDefinition.trigger = adDefinition.trigger || [];
        adDefinition.trigger.push(adElementTrigger);

        //initialize ad element definition
        adElementDefinition = adElementDefinition || {};
        adElementDefinition.elementId = adDefinition.elementId;
        adElementDefinition.triggerImmediately = (typeof adElementDefinition.triggerImmediately === 'undefined' ? true : adElementDefinition.triggerImmediately);

        //add html element for the ad
        if (renderGptAdHtmlElement(adElementDefinition)) {
            //then add ad tags to the context
            list.push(adDefinition);
            KBB.Page.addAdTags(contextNameOrList, list);

            //fire ad impression
            if (adElementDefinition.triggerImmediately) {
                KBB.Page.trigger(adElementTrigger);
            }

            return true;
        }

        return false;
    };

    return {
        //Constants
        AdLoadType: AdLoadType,
        LoadType: LoadType,

        //Fire Ads
        setTestIds: setTestIds,
        renderDynamicAd: renderDynamicAd,
        setupAds: setupAds,
        showAd: showAd,
        trigger: trigger,
        refresh: refresh,
        refreshSection: refreshSection,
        resizeAd: resizeAd,

        //Change context functions
        activateContext: activateContext,
        deactivateContext: deactivateContext,

        setupListeners: setupListeners,
        getVideoAdUrl: getVideoAdUrl,

        isLowerFunnelPage: isLowerFunnelPage,
        isKnownCategoryPage: isKnownCategoryPage,

        //Use for AB Tests
        refreshScrollAds: refreshScrollAds
    };

})();
;
var KBB = KBB || {};

(function () {
    'use strict';

    var constructors = {};

    var createNamespaceAndSet = function (name, obj) {
        var parts = name.split('.'),
            current = window,
            i;

        for (i = 0; i < parts.length - 1; i++) {
            current[parts[i]] = current[parts[i]] || {};
            current = current[parts[i]];
        }

        current[parts[parts.length - 1]] = obj;

        return obj;
    };

    KBB.define = function (name, constructor) {
        return createNamespaceAndSet(name, constructor);
    };

    KBB.getInstance = function (name, args) {
        var constructor = constructors[name];
        return constructor.apply(null, args);
    };

    KBB.create = function (name, constructor, args) {
        if (constructors[name]) {
            console.warn('You already defined the object: ' + name); // eslint-disable-line
        }
        constructors[name] = constructor;
        return createNamespaceAndSet(name, KBB.getInstance(name, args));
    };

    KBB.createAndInit = function (name, constructor, args) {
        var instance = KBB.create(name, constructor, args);
        instance.init();
    };
})();

;
/* globals globalOrd, Mediator, Modernizr */

var KBB = KBB || {};

KBB.Page = (function () {
    'use strict';

    var defaultAds = [],
        contexts = {},
        partnerMappingDictionary = null,
        eventHistory = {},
        referrerTrackingIdsDictionary = null,
        referrerTrackingDomainsDictionary = null,
        mediator = new Mediator(),
        contextStack = ['root'];

    var getDataLayer = function () {
        return KBB.DataLayer[KBB.DataLayer.length - 1];
    };

    var reset = function () {
        contexts = {};
        contextStack = ['root'];
    };

    var getContext = function () {
        return contexts[contextStack[contextStack.length - 1]];
    };

    // sets cookies for psid and siomid (paidsearchid and searchignitetrackingid) when param is available in url
    // omniture info s.prop31 for psid and s.eVar5 for siomid
    var setPaidSearchCookies = function () {
        var dataLayer = getDataLayer();
        var tmpPsid = Utils.getParamByName('psid');
        var tmpSiomid = Utils.getParamByName('siomid');
        var tmpPsidCookie = KBB.storage.getFromCookie('psid') || null;
        var tmpSiomidCookie = KBB.storage.getFromCookie('siomid') || null;

        if (tmpPsid === '' && tmpPsidCookie !== null) {
            dataLayer.paidsearch.paidsearchid = tmpPsidCookie;
        }

        if (tmpSiomid === '' && tmpSiomidCookie !== null) {
            dataLayer.paidsearch.searchignitetrackingid = tmpSiomidCookie;
        }

        if (tmpPsid !== '') {
            dataLayer.paidsearch.paidsearchid = tmpPsid;
            KBB.storage.saveToCookie('psid', dataLayer.paidsearch.paidsearchid);
        }

        if (tmpSiomid !== '') {
            dataLayer.paidsearch.searchignitetrackingid = tmpSiomid;
            KBB.storage.saveToCookie('siomid', dataLayer.paidsearch.searchignitetrackingid);
        }
    };

    /**
     * Replaces all hrefs and or data-urls with data-search-ignite-code attr with psid and session id.
     */
    var initSearchIgniteCodeReplacement = function () {
        var dataLayer = getDataLayer();
        var searchIgniteCode = document.querySelectorAll('[data-search-ignite-code]');

        for (var i = 0; i <= searchIgniteCode.length - 1; i ++) {
            if (typeof searchIgniteCode[i] !== 'undefined') {
                // replace paidsearchid in data-url
                if (searchIgniteCode[i].hasAttribute('data-url')) {
                    var currentDataUrl = searchIgniteCode[i].getAttribute('data-url');
                    searchIgniteCode[i].setAttribute('data-url', currentDataUrl.replace('paidsearchid', dataLayer.paidsearch.paidsearchid).replace('sessionid', dataLayer.sessionid));
                }
                // replace paidsearchid in href
                else {
                    var currentUrl = searchIgniteCode[i].href;
                    searchIgniteCode[i].href = currentUrl.replace('paidsearchid', dataLayer.paidsearch.paidsearchid).replace('sessionid', dataLayer.sessionid);
                }
            }
        }
    };

    /**
     * Utility function that will get a value out of a given object.  If the value is a function, it will execute the function
     * and return the result.  Otherwise it will just return the value
     */
    var getValue = function (fieldName, obj, dataLayer) {
        var field = obj[fieldName];
        return typeof field === 'function' ? field(dataLayer) : field;
    };

    var firePsClientLogging = function () {
        // if the user hasn't opted out of incentives and other PI, we can log their data
        var hasntOptedOut = KBB.cookies.get('kbb_opt_out') !== 'true';
        if (hasntOptedOut) {
            var atcId = KBB.storage.getFromCookie('ATC_ID');

            // TODO for future Victor: update requestedUrl whenever window.location.href changed
            KBB.DataLayer[0].url.requestedurl = window.location.href;
            KBB.DataLayer[0].autotraderid = atcId;

            // prop39 holds the test id
            if (s.prop39) {
                KBB.DataLayer[0].omniture.testid = s.prop39;
            }

            $.ajax({
                type: 'POST',
                async: true,
                url: '/services/psclientlogging',
                data: {
                    'datalayer': JSON.stringify(KBB.DataLayer[0])
                }
            });
        }
    };

    var setupPageInfo = function () {
        var dataLayer = getDataLayer(),
            context = getContext();

        if (context.defaults.superSection) {
            dataLayer.omniture.supersectionname = getValue('superSection', context.defaults, dataLayer);
        }
        if (context.defaults.section) {
            dataLayer.omniture.sectionname = getValue('section', context.defaults, dataLayer);
        }
        if (context.defaults.pageName) {
            dataLayer.omniture.pagename = getValue('pageName', context.defaults, dataLayer);
            context.currentPageName = context.defaults.pageName;
        }
        if (context.defaults.detailPageName) {
            dataLayer.omniture.detailpagename = getValue('detailPageName', context.defaults, dataLayer);
            context.currentDetailPageName = context.defaults.detailPageName;
        }
        context.pageEvents = context.defaults.events;
    };

    var setupReferrerTrackingId = function (href, referrerUrl) {
        var trackingIdCookieName = 'trid',
            defaultTrackingId = '1',
            referralTrackingId = '40',
            trackingValue = ''; // KBB.storage.getFromCookie(trackingIdCookieName);

        // look for the tracking value in the trid QS parameter
        if (href.indexOf('?') !== -1) {
            var qs = Utils.parseQueryString(href.substring(href.indexOf('?')));
            if (qs[trackingIdCookieName] && qs[trackingIdCookieName].length > 0) {
                var trackingId = qs[trackingIdCookieName];
                var trackingIdNum = Number(trackingId);
                if (!isNaN(trackingIdNum)) {
                    // check if trid is a number
                    if (trackingIdNum > 1000) {
                        // trid values above 1,000 are pass through values which will not be looked up
                        trackingValue = trackingId;
                    } else {
                        // if less than 1000, look up corresponding tracking value for the id from the referrer tracking id mapping table
                        if (referrerTrackingIdsDictionary[trackingIdNum]) {
                            trackingValue = referrerTrackingIdsDictionary[trackingIdNum];
                        }
                    }
                }
            }
        }

        // if no tracking id passed in url, or value not found in config engine, check based on referrer (if available, and not = kbb.com)
        if (trackingValue === '' && (referrerUrl || referrerUrl !== '')) {
            var domain = Utils.getDomainFromUrl(referrerUrl);

            // ignore kbb.com domain
            if (domain.indexOf('kbb.com') === -1) {
                if (referrerTrackingDomainsDictionary[domain]) {
                    // look up the cooresponsing tracking value for the domain from the referrer domain mapping table
                    trackingValue = referrerTrackingDomainsDictionary[domain];
                } else {
                    // if no value for referring host, then set the tracking value to the referral tracking id mapping
                    trackingValue = referrerTrackingIdsDictionary[referralTrackingId];
                }
            }
        }

        // if no trackingValue, check for it in the cookie
        if (trackingValue === '') {
            trackingValue = KBB.storage.getFromCookie(trackingIdCookieName);
        }

        // if trackingValue is still not found, then use default tracking id for a direct link
        if (trackingValue === '' || trackingValue === null) {
            trackingValue = referrerTrackingIdsDictionary[defaultTrackingId];
        }

        // save the trackingValue to the TrackingId cookie
        KBB.cookies.set(trackingIdCookieName, trackingValue);

        // set the trackingId in the data Layer
        getDataLayer().trackingid = trackingValue;
    };

    //GUID for session ID
    var createGuid = function () {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    };

    //client-side version of session filter attribute which populates sessionid and visitorid in the data layer
    var setupSessionData = function () {
        var sessionIdCookieName = 'SessionId',
            visitorIdCookieName = 'VisitorId',
            visitorIdCookieExpiration = 30,
            visitorId = KBB.storage.getFromCookie(visitorIdCookieName),
            sessionId = KBB.storage.getFromCookie(sessionIdCookieName);

        if (!sessionId) {
            sessionId = createGuid();
            KBB.cookies.set(sessionIdCookieName, sessionId);
        }

        if(!visitorId) {
            visitorId = createGuid();
            KBB.cookies.set(visitorIdCookieName, visitorId, visitorIdCookieExpiration);
        }

        var dataLayer = getDataLayer();
        dataLayer.session = { sessionid: sessionId, visitorid: visitorId };
        dataLayer.sessionid = sessionId;
        dataLayer.kbbvisitorid = visitorId;
        ssId = sessionId;
    };

    var initDataLayer = function () {
        var dataLayer = getDataLayer(),
            context = getContext(),
            isPortrait = KBB.Device.getOrientation() === KBB.Device.Portrait,
            maxSide = Math.max(window.screen.width, window.screen.height),
            minSide = Math.min(window.screen.width, window.screen.height);

        //Fields that are set only when the page loads
        dataLayer.device.width = isPortrait ? minSide : maxSide;
        dataLayer.device.height = isPortrait ? maxSide : minSide;
        dataLayer.pageinstance = globalOrd;
        context.pageInstance = globalOrd;

        setupPageInfo();
        setupSessionData();
        setPaidSearchCookies();
        setupReferrerTrackingId(window.location.href, document.referrer);
    };

    var hasRefreshRule = function (context, triggerName) {
        var i,
            thisTrigger,
            triggers;

        for (i = 0; i < context.refreshRules.length; i++) {
            thisTrigger = context.refreshRules[i].trigger;
            triggers = thisTrigger instanceof Array ? thisTrigger : [thisTrigger];

            if (triggers.indexOf(triggerName) !== -1) {
                return true;
            }
        }
        return false;
    };

    var addList = function (contextNameOrList, list, listName, listTransform) {
        var contextName = typeof contextNameOrList === 'string' ? contextNameOrList : 'root',
            i;

        list = typeof contextNameOrList === 'string' ? list : contextNameOrList;
        contexts[contextName][listName] = contexts[contextName][listName].concat(list);
        if (listTransform) {
            for (i = 0; i < list.length; i++) {
                listTransform(list[i]);
            }
        }

        return contextName;
    };

    var refresh = function (onlyRefreshVisibleAds) {
        //Deprecated, please use the new omniture / ad framework
        KBB.omniture.resubmit();
        KBB.ads.helpers.refreshAds(onlyRefreshVisibleAds);
    };

    var init = function (cfg) {
        KBB.Page.createContext('root', cfg);
        //Create a zipcode context
        KBB.Page.createContext('ZipCode', Utils.extend({}, cfg, {
            pageName: function (dataLayer) {
                return dataLayer.targetexperience !== 'desktop' ? getValue('pageName', cfg, dataLayer) + '_zip' : dataLayer.omniture.pagename;
            },
            detailPageName: function (dataLayer) {
                return dataLayer.targetexperience !== 'desktop' ? getValue('detailPageName', cfg, dataLayer) + '_zip' : dataLayer.omniture.detailpagename;
            }
        }));

        //Create a printpage context
        KBB.Page.createContext('PrintPage', Utils.extend({}, cfg, {
            pageName: 'printpage',
            detailPageName: 'printpage',
            superSection: 'other',
            section: 'print',
            setup: function (dataLayer) {
                dataLayer.omniture.previouspagename = getValue('pageName', cfg, dataLayer);
            }
        }));

        //Create a geolocation context
        KBB.Page.createContext('GeoLocation', Utils.extend({}, cfg, {
            pageName: function (dataLayer) {
                return dataLayer.targetexperience !== 'desktop' ? getValue('pageName', cfg, dataLayer) + '_loc' : dataLayer.omniture.pagename;
            },
            detailPageName: function (dataLayer) {
                return dataLayer.targetexperience !== 'desktop' ? getValue('detailPageName', cfg, dataLayer) + '_loc' : dataLayer.omniture.detailpagename;
            },
            superSection: 'location',
            section: 'geolocal'
        }));

        //Create a responsive overlay context
        KBB.Page.createContext('ResponsiveOverlay', Utils.extend({}, cfg, {
            pageName: null,
            detailPageName: null,
            noTracking: true,
            preventAdRefresh: true
        }));
    };

    //Create a Context for adding omniture and ad tags to
    var createContext = function (name, cfg) {
        var props = ['loadAdsBySection', 'disableAdMappings', 'gptLoadType', 'sectionViewTop', 'previouspagename', 'setup'],
            defaults = {},
            contextProps = {},
            field;

        if (contexts[name]) {
            throw new Error('Context with name ' + name + ' already exists');
        }

        for (field in cfg) {
            if (props.indexOf(field) === -1) {
                defaults[field] = cfg[field];
            }
            else {
                contextProps[field] = cfg[field];
            }
        }


        contexts[name] = Utils.extend(contextProps, {
            name: name,
            defaults: defaults,
            tags: [],
            pageSections: [],
            refreshRules: [],
            ads: [],
            gptAds: {}
        });
    };

    var refreshOn = function (contextNameOrList, list) {
        addList(contextNameOrList, list, 'refreshRules');
    };

    var addAdTagDefault = function (ad) {
        defaultAds.push(ad);
    };

    var adTagDefaults = function (list) {
        defaultAds = list;
    };

    var addAnalyticsTags = function (contextNameOrList, list) {
        addList(contextNameOrList, list, 'tags');
    };

    var addAdTags = function (contextNameOrList, list) {
        var contextName = addList(contextNameOrList, list, 'ads'),
            context = contexts[contextName],
            i,
            j;

        //Take the defaults and merge it with the list of page specific ads
        for (i = 0; i < context.ads.length; i++) {
            for (j = 0; j < defaultAds.length; j++) {
                if (defaultAds[j].adId === context.ads[i].adId) {
                    context.ads[i] = Utils.extend({}, defaultAds[j], context.ads[i]);
                }
            }
        }


    };

    var addPageSections = function (contextNameOrList, list) {
        addList(contextNameOrList, list, 'pageSections', function (section) {
            section.type = 'section';
            section.overrides = section.overrides || {};
            section.overrides.detailPageName = section.tag;
        });
    };

    var trigger = function (eventName, data) {
        var context = KBB.Page.getContext();

        mediator.trigger(eventName + '.before', data);

        if (KBB.Analytics) {
            KBB.Analytics.triggerEvent(context, eventName, data);
        }

        if (hasRefreshRule(context, eventName)) {
            //Fire the PS Client after a page view
            firePsClientLogging();

            //The page was refreshed
            KBB.Ads.refresh(context);

            if (context.lastSection) {
                KBB.Ads.refreshSection(context.lastSection);
            }
        }

        KBB.Ads.trigger(context, eventName, data);
        triggerMediator(eventName, data);
    };

    var triggerMediator = function(eventName, data) {
        eventHistory[eventName] = { data: data };
        mediator.trigger(eventName, data);
    };

    var on = function (eventName, handler, includeLastCall) {
        if (includeLastCall && eventHistory[eventName]) {
            // This is if we care about events that fired in the past
            // mainly used for mykbb and when the user is loaded since we are not
            // sure when we will get the user data or if its even an ajax call
            handler(eventHistory[eventName].data);
        }

        return mediator.on(eventName, handler);
    };

    // Remove/unsubscribe an event from mediator
    var off = function (eventName, id) {
        if (id) {
            mediator.off(eventName, id);
        } else {
            mediator.off(eventName);
        }
        return this;
    };

    var setInitialContext = function (contextName) {
        if (contextName) {
            contextStack.push(contextName);
        }
        else {
            throw new Error('Cannot set empty context');
        }
    };

    var getRealDetailPageName = function (context) {
        if (context.lastSection && context.lastSection.tag) {
            return context.lastSection.tag.detailPageName;
        }
        return null;
    };

    var initContext = function (contextName) {
        //Used primarily for setting the first context if it is not root
        var dataLayer = getDataLayer(),
            context = contexts[contextName],
            prevContext = getContext();

        if (context) {
            contextStack.push(contextName);
            //Update the data layer page info
            context.previouspagename = dataLayer.omniture.pagename; //Set the previous page name
            context.currentPageName = context.defaults.pageName || prevContext.currentPageName;


            context.currentDetailPageName = context.defaults.detailPageName || prevContext.currentDetailPageName;

            setupPageInfo();
        }
        else {
            throw new Error('Cannot set to context with name ' + contextName + ' since it does not exists');
        }
    };

    var setContext = function (contextName) {
        var context = contexts[contextName];

        if (context) {
            context.currentWidth = document.documentElement.clientWidth;

            initContext(contextName);
            //Fire whatever omniture and ad requirements there are
            if (KBB.Analytics) {
                KBB.Analytics.activateContext(contexts[contextName]);

                //Fire the PS Client after a page view
                if (context.defaults && !context.defaults.noTracking) {
                    firePsClientLogging();
                }
            }
            if (KBB.Ads) {
                KBB.Ads.activateContext(contexts[contextName]);
            }
        }
        else {
            throw new Error('Cannot set to context with name ' + contextName + ' since it does not exists');
        }
    };

    var forceRefresh = function () {
        var context = KBB.Page.getContext();

        if (context.currentWidth !== document.documentElement.clientWidth) {
            context.currentWidth = document.documentElement.clientWidth;

            if (KBB.Analytics) {
                KBB.Analytics.triggerReload(context, '', {});
            }

            if (KBB.Ads) {
                googletag.pubads().updateCorrelator();

                if (context.defaults && !context.defaults.preventAdRefresh) {
                    //The page was refreshed
                    KBB.Ads.refresh(context);

                    if (context.lastSection) {
                        KBB.Ads.refreshSection(context.lastSection);
                    }
                }
            }
        }
    };

    var prevContext = function () {
        var previousContext = KBB.Page.getContext(),
            currentContext,
            dataLayer = KBB.Page.getDataLayer();

        if (contextStack.length > 1) {
            contextStack.pop();

            //Update the data layer page info
            setupPageInfo();

            //Fire whatever omniture and ad requirements there are
            KBB.Analytics.deactivateContext(KBB.Page.getContext(), previousContext);
            if (KBB.Ads) {
                KBB.Ads.deactivateContext(KBB.Page.getContext(), previousContext);
            }

            forceRefresh();

            //get the real detail page name if section view has fired
            currentContext = KBB.Page.getContext();
            currentContext.currentDetailPageName = getRealDetailPageName(currentContext) || currentContext.currentDetailPageName;

            //sync the omniture detailpagename
            //remove when the timing of Omniture page call, Ads, and Omniture section call is consistent for page load and context refreshes
            dataLayer.omniture.detailpagename = getValue('detailPageName', { 'detailPageName': currentContext.currentDetailPageName }, dataLayer);

        }
    };

    var setupPage = function () {
        var ctx;
        var dl = getDataLayer();

        if (dl) {
            //setup initial context to zip code if the page name ends with _zip
            if (dl.omniture && dl.omniture.pagename && dl.omniture.pagename.indexOf('_zip') > 0) {
                setInitialContext('ZipCode');
            } else if (dl.displayzipcodeoverlay) {
                //This is for M1 pages only
                //specify the initial context for zipcode
                //M1 to add this back when needed
                initContext('ZipCode');
            }

            //setup initial context to PrintPage if the page name is printpage
            if (dl.isprintablepage) {
                setInitialContext('PrintPage');
            }

            ctx = getContext();

            initDataLayer();

            //setup ads
            KBB.Ads.setupAds(ctx.ads, ctx.gptLoadType || KBB.Ads.LoadType.AsyncSRA);
        }

        if (KBB.Page.getDataLayer().flippers.KBBRUM || KBB.Page.getDataLayer().flippers.kbbrum) {
            /* eslint-disable */
            BOOMR.subscribe('before_beacon', function (o) {
                BOOMR.addVar({
                    pg: KBB.Page.getDataLayer().omniture.pagename,
                    dpg: KBB.Page.getDataLayer().omniture.detailpagename,
                    pg_inst: KBB.Page.getDataLayer().pageinstance,
                    kid: KBB.Page.getDataLayer().kbbvisitorid,
                    deviceType: KBB.Page.getDataLayer().device.istablet ? 'tablet': (KBB.Page.getDataLayer().device.issmartphone ? 'smartphone': 'desktop')
                });
            });

            BOOMR.init({
                beacon_url: '/boomerang/?dontlower=true'
            });
            /* eslint-enable */
        }
    };


    var getSectionGroup = function (el, context) {
        var numLoadAds = getValue('numLoadAds', context.defaults);

        return numLoadAds ? Math.ceil(el.getAttribute('data-section-index') / numLoadAds) : el.getAttribute('data-section-group');
    };

    var getSectionData = function (sectionElement) {
        var context = KBB.Page.getContext(),
            i;

        for (i = 0; i < context.pageSections.length; i++) {
            if ($(sectionElement).is(context.pageSections[i].selector)) {
                return {
                    el: sectionElement,
                    tag: context.pageSections[i],
                    group: getSectionGroup(sectionElement, context)
                };
            }
        }

        return null;
    };

    /**
     * Function to find the first visible section.  Note that it checks in the order listed in the section list.
     * This list must be updated if a section is moved
     *
     * @param context {Object} The context object that defines the sections to check
     */
    var getVisibleSection = function () {
        var selectors = [],
            context = getContext(),
            sectionTop = context.sectionViewTop || 0,
            i,
            sectionTag,
            sectionElement,
            sectionData,
            $sections;

        for (i = 0; i < context.pageSections.length; i++) {
            sectionTag = context.pageSections[i];

            if (sectionTag.selector) {
                selectors.push(sectionTag.selector);
            }
        }

        if (typeof sectionTop === 'string' && sectionTop.endsWith('%')) {
            sectionTop = KBB.Page.getDataLayer().device.height * sectionTop.substring(0, sectionTop.length - 1) / 100;
        }

        $sections = $(selectors.join(','));
        for (i = 0; i < $sections.length; i++) {
            sectionElement = $sections.get(i);

            if (Utils.elementInViewport(sectionElement, sectionTop)) {
                sectionData = getSectionData(sectionElement);

                if (sectionData) {
                    return sectionData;
                }
            }
        }

        return null;
    };

    var fireSectionView = function (sectionData) {
        var context = KBB.Page.getContext();

        if (sectionData && (!context.lastSection || context.lastSection.el !== sectionData.el)) {
            //If the new section in view is the same as what we fired previous, don't
            //fire anything
            context.lastSection = sectionData;

            if (KBB.Analytics) {
                KBB.Analytics.triggerSectionView(sectionData);
                //Fire the PS Client after a page view
                KBB.Page.firePsClientLogging();
            }

            if (context.lastSectionGroup === null || context.lastSectionGroup !== sectionData.group) {
                //For Ads,we refresh the entire section group rather than just the section
                KBB.Ads.refreshSection(sectionData);
            }
            else {
                KBB.Page.trigger('sectionViewComplete');
            }

            context.lastSectionGroup = sectionData.group;

            //This was code in the previous implementation, not sure if we still need it
            $(context.lastSection.el).trigger('sectionInView');
            $(document).trigger('sectionInView');
        }
        else {
            KBB.Page.trigger('sectionViewComplete');
        }
    };

    var setReferrerTrackingIdMappings = function (mappings) {
        referrerTrackingIdsDictionary = mappings;
    };

    var setReferrerTrackingDomainMappings = function (mappings) {
        referrerTrackingDomainsDictionary = mappings;
    };

    var setPartnerMappings = function (mappings) {
        partnerMappingDictionary = mappings;
    };

    var partner = function (partnerType) {
        return partnerMappingDictionary[partnerType] ? partnerMappingDictionary[partnerType] : 'nx';
    };

    var addLegacyAnalyticsTags = function (tags) {
        if (!KBB.Omniture) {
            document.body.addEventListener('click', function(event) {
                for (var i = 0; i < tags.length; i++) {
                    if (tags[i].type.indexOf('click') !== -1) {
                        var el = DomUtils.matchingParent(document.body, event.target, tags[i].selector);
                        if (el) {
                            KBB.omniture.link(tags[i].tag(), 'nx', el);
                        }
                    }
                }
            });
        }
    };

    return {
        //Placeholder object to store event constants
        Events: {},

        //Deprecated Function
        refresh: refresh,

        // Cookie Paid search ID's
        setPaidSearchCookies: setPaidSearchCookies,
        initSearchIgniteCodeReplacement: initSearchIgniteCodeReplacement,

        //Context Creation Functions
        init: init,
        reset: reset,
        createContext: createContext,
        refreshOn: refreshOn,
        addAdTagDefault: addAdTagDefault,
        adTagDefaults: adTagDefaults,
        addAnalyticsTags: addAnalyticsTags,
        addAdTags: addAdTags,
        addPageSections: addPageSections,
        // Function to polyfill for pages that do not have the complete framework
        addLegacyAnalyticsTags: addLegacyAnalyticsTags,

        //Functions to interact with the ad / omniture framework
        trigger: trigger,
        on: on,
        off: off,
        getContext: getContext,
        initContext: initContext,
        setContext: setContext,
        setInitialContext: setInitialContext,
        prevContext: prevContext,
        setupPage: setupPage,

        //Get the datalayer
        getDataLayer: getDataLayer,
        //Gets the first visible section
        getVisibleSection: getVisibleSection,
        getSectionGroup: getSectionGroup,

        //Partner Functions
        setPartnerMappings: setPartnerMappings,
        partner: partner,

        //Referrer Tracking
        setReferrerTrackingIdMappings: setReferrerTrackingIdMappings,
        setReferrerTrackingDomainMappings: setReferrerTrackingDomainMappings,
        setupReferrerTrackingId: setupReferrerTrackingId, // expose for unit tests

        firePsClientLogging: firePsClientLogging,
        //Special Function to force a refresh.  Primarily used for rotation
        forceRefresh: forceRefresh,
        fireSectionView: fireSectionView,
        getSectionData: getSectionData
    };
})();

//Broke this portion out because it is called at the very bottom of the page even though it is declared at the
//top of the page.  This means we can use jquery in this function
KBB.Page.setupListeners = (function (window, document) {
    'use strict';
    //Stuff to manage swipe detection
    var startX,
        startY,
        swipedElement;


    //Fire a section view
    var sectionViewHandler = function () {
        var context = KBB.Page.getContext();

        KBB.Page.fireSectionView(KBB.Page.getVisibleSection());

        KBB.Ads.refreshScrollAds(context);
    };

    var swipeStartHandler = function (event) {
        if (KBB.Analytics.hasSwipeTags(KBB.Page.getContext(), event.target)) {
            startX = event.pageX;
            startY = event.pageY;
            swipedElement = this;
        }
    };

    var swipeEndHandler = function (event) {
        var context = KBB.Page.getContext(),
            deltaX, deltaY;

        if (swipedElement) {
            deltaX = Math.abs(event.pageX - startX);
            deltaY = Math.abs(event.pageY - startY);

            if (deltaX && deltaX > deltaY) {
                KBB.Analytics.triggerSwipe(context, event.target);
            }
            startX = startY = swipedElement = undefined;
        }
    };

    var clickHandler = function (event) {
        KBB.Analytics.triggerClick(KBB.Page.getContext(), event.target);
    };

    return function () {
        var $document = $(document),
            $window = $(window),
            touchEvent = $.getTouchEvent('Page'),
            touchStartEvent = $.getTouchStartEvent('Page'),
            endSwipeListener = ((Modernizr.android || Modernizr.silk) ? $.getTouchMoveEvent() : $.getTouchEndEvent()) + '.Analytics',
            context = KBB.Page.getContext();

        //Fire a page refresh (includes refresh, section view and impressions)
        if (KBB.Analytics) {
            //Move call ahead so that datalayer has not been messed with yet
            KBB.Page.firePsClientLogging();
            //Fire the first Page Call
            KBB.Analytics.triggerReload(context, null, true);
        }

        if (KBB.Ads && context.lastSection) {
            KBB.Ads.refreshSection(context.lastSection, true);
        }

        //Add any listeners
        $window.on('delayedload.viewedOmniture', sectionViewHandler);
        $window.on('throttledscroll.viewedOmniture', sectionViewHandler);
        $document.on('lazyLoaded.viewedOmniture', sectionViewHandler);
        $document.on('iscrollend.viewedOmniture', sectionViewHandler);
        $document.on(touchEvent, clickHandler);
        $document.on(touchStartEvent, swipeStartHandler);
        $document.on(endSwipeListener, Utils.debounce(swipeEndHandler, 500));


        //Rotation Code (Temp for TD)
        context.currentWidth = document.documentElement.clientWidth;
        if (KBB.DataLayer[0].device.ismobiledevice) {
            $window.on('resize', Utils.debounce(function () {
                KBB.Page.forceRefresh();
                KBB.Page.trigger(KBB.Page.Events.AdsReshreshedOnRotation);
            }, 1000));
        }

        Utils.getMediator().subscribe(Utils.eventTypes.resizeAd, KBB.Ads.resizeAd);

    };
})(window, document);
;
var KBB = KBB || {};
KBB.Page = KBB.Page || {};

KBB.Page.Events = {
    MyKbbUserChanged: 'MyKbbUserChanged',
    MyKbbPageChanged: 'MyKbbPageChanged',

    ZipCodeChange: 'ZipCodeChange',
    //Event that fires when the user requests GeoLocation via SLP or hamburger menu
    GeoLocationRequestComplete: 'GeoLocationRequestComplete',

    //
    AdsReshreshedOnRotation: 'AdsReshreshedOnRotation',

    BrowseCategoryMakeTabChange: 'BrowseCategoryMakeTabChange',
    CategoryOverlay: 'CategoryOverlay',
    CategoryOverlayClear: 'CategoryOverlayClear',
    GlobalOverlay: 'GlobalOverlay',
    GlobalOverlayClear: 'GlobalOverlayClear',
    ResponsiveOverlay: 'ResponsiveOverlay',
    ResponsiveOverlayClear: 'ResponsiveOverlayClear',
    NcMpgTab: 'NcMpgTab',
    NcMpgBanner: 'NcMpgBanner',
    NcOemTab: 'NcOemTab',
    UcOemTab: 'UcOemTab',
    NcOemModel: 'NcOemModel',
    UcOemModel: 'UcOemModel',
    NcOemCategory: 'NcOemCategory',
    UcOemCategory: 'UcOemCategory',
    NcModelSearchBanner: 'NcModelSearchBanner',
    UcModelSearchBanner: 'UcModelSearchBanner',
    SponsoredTabChange: 'SponsoredTabChange',
    NcOemMatch: 'NcOemMatch',
    ShowroomPanelChange: 'ShowroomPanelChange',
    ShowroomShowItem1: 'ShowroomShowItem1',
    ShowroomShowItem2: 'ShowroomShowItem2',
    ShowroomShowItem3: 'ShowroomShowItem3',
    ShowroomShowThumbnails: 'ShowroomShowThumbnails',
    Toolbar: 'ToolbarExpanded',
    VideoShowcase: 'VideoShowcase',
    VideoSponsoredThumbnail: 'VideoSponsoredThumbnail',
    CategoryCarouselMedRec1: 'CategoryCarouselMedRec1',
    CategoryCarouselMedRec2: 'CategoryCarouselMedRec2',
    CategoryCarouselMedRec3: 'CategoryCarouselMedRec3',
    CategorySponsoredLink1: 'CategorySponsoredLink1',
    CategorySponsoredLink2: 'CategorySponsoredLink2',
    CategorySponsoredLink3: 'CategorySponsoredLink3',
    CategorySponsoredLink4: 'CategorySponsoredLink4',
    CategorySponsoredLink5: 'CategorySponsoredLink5',
    CategorySponsoredLink6: 'CategorySponsoredLink6',
    CategorySponsoredLink7: 'CategorySponsoredLink7',
    CategorySponsoredLink8: 'CategorySponsoredLink8',
    CategorySponsoredLink9: 'CategorySponsoredLink9',
    Banner1: 'Banner1',
    ClassifiedsInlineOem: 'ClassifiedsInlineOem',
    ClassifiedsInlineOem2: 'ClassifiedsInlineOem2',
    ClassifiedsInlineOemClear: 'ClassifiedsInlineOemClear',
    ClassifiedsInlineOem2Clear: 'ClassifiedsInlineOem2Clear',
    UsedUpgradeA: 'UsedUpgradeA',
    UsedUpgradeB: 'UsedUpgradeB',
    UsedUpgradeCompare: 'UsedUpgradeCompare',
    TopReviews: 'TopReviews',
    ModelCenterYearDropdown: 'ModelCenterYearDropdown',

    // Classifieds M1 Events
    SocialFeedRefresh: 'SocialFeedRefresh',
    ShowSimilarCars: 'ShowSimilarCars',
    ModalClose: 'ModalClose', //jqm event since they stop propagation
    ChatNowShow: 'ChatNowShow',
    DistanceChange: 'DistanceChange',
    ClassifiedsRequestZip: 'ClassifiedsRequestZip',
    ClassifiedsSrpSort: 'ClassifiedsSrpSort',
    ClassifiedsSrpShowHeader: 'ClassifiedsSrpShowHeader',
    ClassifiedsDetailTab: 'ClassifiedsDetailTab',
    ClassifiedsCarouselEnd: 'ClassifiedsCarouselEnd',
    ClassifiedsToyotaCentralClose: 'ClassifiedsToyotaCentralClose',
    // Classifieds SEP
    ClassifiedsToggleOptions: 'ClassifiedsToggleOptions',
    ClassifiedsNoResults: 'ClassifiedsNoResults',
    ClassifiedsThreholdResults: 'ClassifiedsThreholdResults',
    ClassifiedsTimeoutResult: 'ClassifiedsTimeoutResult',
    // Classifieds New SEP
    ClassifiedsMakeDropdown: 'ClassifiedsMakeDropdown',
    ClassifiedsModelDropdown: 'ClassifiedsModelDropdown',
    ClassifiedsPriceHighDropdown: 'ClassifiedsPriceHighDropdown',
    ClassifiedsPriceLowDropdown: 'ClassifiedsPriceLowDropdown',
    ClassifiedsRadiusDropdown: 'ClassifiedsRadiusDropdown',
    ClassifiedsLocalInventoryBrowseDealer: 'ClassifiedsLocalInventoryBrowseDealer',
    ClassifiedsYearHighDropdown: 'ClassifiedsYearHighDropdown',
    ClassifiedsYearLowDropdown: 'ClassifiedsYearLowDropdown',
    ClassifiedsViewResults: 'ClassifiedsViewResults',
    // Classifieds New SRP
    ClassifiedsUpdateResults: 'ClassifiedsUpdateResults',
    ClassifiedsMainElite: 'ClassifiedsMainElite',
    // Classifieds VDP
    ClassifiedsDetailOtherCars: 'ClassifiedsDetailOtherCars',
    // Classifieds Lead Form
    ClassifiedsLeadSubmit: 'ClassifiedsLeadSubmit',
    ClassifiedsLeadSubmitConfirm: 'ClassifiedsLeadSubmitConfirm',
    ClassifiedsLeadSend: 'ClassifiedsLeadSend',
    ClassifiedsLeadSubmitClick: 'ClassifiedsLeadSubmitClick',
    // Classifieds Facets (Refine Search)
    ClassifiedsFacetSubmit: 'ClassifiedsFacetSubmit',
    ClassifiedsListingOpenFacet: 'ClassifiedsListingOpenFacet',
    // Classifieds Listings
    ClassifiedsListingCarouselSelect: 'ClassifiedsListingCarouselSelect',
    ClassifiedsListingLoad: 'ClassifiedsListingLoad',
    ClassifiedsListingExpandMax: 'ClassifiedsListingExpandMax',
    ClassifiedsListingExpandNone: 'ClassifiedsListingExpandNone',
    ClassifiedsQuickViewClose: 'ClassifiedsQuickViewClose',
    DealerDiffLoad: 'DealerDiffLoad',
    // Classifieds Spotlight
    ClassifiedsSpotlightShow: 'ClassifiedsSpotlightShow',
    // Local Inventory
    ClassifiedsLocalInventoryClick: 'ClassifiedsLocalInventoryClick',
    ClassifiedsRefineSearch: 'ClassifiedsRefineSearch',
    ClassifiedsQuickViewClick: 'ClassifiedsQuickViewClick',
    CalculatePayment: 'CalculatePayment',
    MicrositeOverviewPhotoClick: 'MicrositeOverviewPhotoClick',
    MicrositeInventoryResubmit: 'MicrositeInventoryResubmit', //Called when we click on dropdowns
    MicrositeInventoryRefresh: 'MicrositeInventoryRefresh', //Called after new results come in
    MiscrositeLeadSubmit: 'MiscrositeLeadSubmit',
    // Classifieds Inline Ad
    ClassifiedsInlineAd1: 'ClassifiedsInlineAd1',
    ClassifiedsInlineAd2: 'ClassifiedsInlineAd2',
    ClassifiedsInlineAd3: 'ClassifiedsInlineAd3',
    ClassifiedsInlineAd4: 'ClassifiedsInlineAd4',
    ClassifiedsInlineAd5: 'ClassifiedsInlineAd5',
    // Classifieds New VDP
    KbbAdsLeaderboardVDP: 'KbbAdsLeaderboardVDP',
    ClassifiedsAboutDealerWebsite: 'ClassifiedsAboutDealerWebsite',
    ClassifiedsInstantCashOffer: 'ClassifiedsInstantCashOffer',
    ClassifiedsCpoBage: 'ClassifiedsCpoBage',
    ClassifiedsDealerDifferentiator: 'ClassifiedsDealerDifferentiator',
    ClassifiedsDealerDifferentiatorClick: 'ClassifiedsDealerDifferentiatorClick', // Called when we click button

    //FDPQ
    FDPQStep2NoDealer: 'FDPQStep2NoDealer',
    FDPQStep2TooSoon: 'FDPQStep2TooSoon',

    // Dealers overview
    DealerOverviewTab: 'DealerOverviewTab',

    //Owners Styles Page
    OwnersCategorySelected: 'OwnerCategorySelected',

    //Owners Option Page
    ToggleOptions: 'ToggleOptions',

    // Used Car YMMT Page
    UsedCarHighlightModule: 'UsedCarHighlightModule',

    // Owners YMMT Page
    YmmtLoadingClick: 'YmmtLoadingClick',
    YmmtConditionChange: 'YmmtConditionChange',
    YmmtStyleChange: 'YmmtStyleChange',
    DesktopPhotosTabs: 'desktopgallerytab',
    SpecsTabChange: 'SpecsTabChange',
    SpecsModalTabChange: 'SpecsModalTabChange',
    MonthlyBudgetCalc: 'MonthlyBudgetCalc',
    MeterConditionClick: 'MeterConditionClick',

    //GeoLocation
    GeoLocationAllow: 'GeoLocationAllow',
    GeoLocationDecline: 'GeoLocationDecline',

    // Deal Advisor
    DealAdvisorFppAccordionExpanded: 'DealAdvisorFppAccordionExpanded',
    DealAdvisorFppAccordionCollapsed: 'DealAdvisorFppAccordionCollapsed',

    DealAdvisorTradeInAccordionExpanded: 'DealAdvisorTradeInAccordionExpanded',
    DealAdvisorTradeInAccordionCollapsed: 'DealAdvisorTradeInAccordionCollapsed',
    DealAdvisorTradeInNo: 'DealAdvisorTradeInNo',
    DealAdvisorTradeInYes: 'DealAdvisorTradeInYes',
    DealAdvisorTradeInNext: 'DealAdvisorTradeInNext',
    DealAdvisorFinancingAccordionExpanded: 'DealAdvisorFinancingAccordionExpanded',
    DealAdvisorFinancingAccordionCollapsed: 'DealAdvisorFinancingAccordionCollapsed',
    DealAdvisorFinancingFinish: 'DealAdvisorFinancingFinish',
    DealAdvisorFinancingFinishWithSliderMoved: 'DealAdvisorFinancingFinishWithSliderMoved',
    DealAdvisorTradeInGetYourCarValue: 'DealAdvisorTradeInGetYourCarValue',
    DealAdvisorTradeInValueAnotherCar: 'DealAdvisorTradeInValueAnotherCar',
    DealAdvisorSendEmail: 'DealAdvisorSendEmail',
    DealAdvisorSendEmailWithOptin: 'DealAdvisorSendEmailWithOptin',

    // TradeInValueModal
    TradeInValueModalStep1Shown: 'TradeInValueModalStep1Shown',
    TradeInValueModalStep2Shown: 'TradeInValueModalStep2Shown',
    TradeInValueModalStep3Shown: 'TradeInValueModalStep3Shown',
    TradeInValueModalClosing: 'TradeInValueModalClosing',
    TradeInValueModalConditionStepCompleted: 'TradeInValueModalConditionStepCompleted',

    // Incentives
    IncentivesFormSubmitError: 'IncentivesFormSubmitError',
    IncentivesRetrieved: 'IncentivesRetrieved',
    IncentivesOfferAvailable: 'IncentivesOfferAvailable',
    IncentivesShowRibbon: 'IncentivesShowRibbon',

    SponsoredChipModal: 'SponsoredChipModal',
    KioskVideoModalMma: 'KioskVideoModalMma',
    KioskVideoModalMmaClear: 'KioskVideoModalMmaClear',

    //Toyota Hub
    MakeHubStm: 'MakeHubStm',
    MakeHubMedRec: 'MakeHubMedRec',

    //RCM
    SmartphoneRcmPanel: 'SmartphoneRcmPanel',
    SponsoredRcmPanel: 'SponsoredRcmPanel',

    //adblockerblocker
    AbbComplete: 'AbbComplete',
    AbbFirstVisit: 'AbbFirstVisit',
    AbbStatusChange: 'AbbStatusChange',

    //Cross-site
    CrossSiteATCCookieFound: 'CrossSiteATCCookieFound',

    // Targeted Incentives
    TargetedIncentivesShowRibbon: 'TargetedIncentivesShowRibbon',
    TargetedIncentivesSignupValidationError: 'TargetedIncentivesSignupValidationError',
    TargetedIncentivesContactinfo: 'TargetedIncentivesContactinfo',
    TargetedIncentivesDealerSelect: 'TargetedIncentivesDealerSelect',
    TargetedIncentivesInvalid: 'TargetedIncentivesInvalid',
    TargetedIncentivesGeneralError: 'TargetedIncentivesGeneralError',

    GlobalNavClosed: 'GlobalNavClosed',
    // Homepage Events
    PopularOnKbb: 'PopularOnKbb'
};
;
var KbbErrorHandler = (function () {
    'use strict';
    var currentErrors = [],
        errorDelay = 5000,
        baseUrl = (self.location.protocol === 'https:' ? 'https' : 'http') + '://' + self.location.hostname + '/error/',
        urls = {
            logError: baseUrl + 'JsLogger/',
            logErrors: baseUrl + 'JsErrorsLogger/'
        },
        xmlhttp = new XMLHttpRequest(),
        sendErrorsTimer = null,
        post = function (url, params) {
            xmlhttp.open('POST', url, true);
            xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
            xmlhttp.send(params);
        };

    return {
        onerror: function (m, u, n, e) {
            if (m) {
                //Log to server
                if (window.errorJsLogging) {
                    try {
                        /* Push reported error to the stack */
                        currentErrors.push({
                            message: m,
                            source: u,
                            line: n
                        });

                        clearTimeout(sendErrorsTimer);
                        sendErrorsTimer = setTimeout(KbbErrorHandler.sendErrors, errorDelay);
                    }
                    catch (e) {
                        // catch exception
                    }
                }

                var output = ['[ERROR]\t']; //Very important first element, do not modify!
                if (e instanceof Error) {
                    output.push(e.message + '\n');
                    output.push(e);
                } else {
                    output.push('Message: ' + m + ' Line: ' + n + ' Source: ' + u + '\n');
                    if (e && m !== e) {
                        output.push(e);
                    }
                }
                /*eslint-disable no-console */
                if (console.error.apply) {
                    console.error.apply(console, output);
                } else {
                    console.error(Array.prototype.join.call(output, ' '));
                }
                /*eslint-enable no-console */
            }
        },
        sendErrors: function () {
            if (!currentErrors || !currentErrors.length) {
                return;
            }

            var params = 'ua=' + encodeURIComponent(navigator.userAgent) + '&l=' + encodeURIComponent(self.location) + '&errors=';

            for (var i = 0; i < currentErrors.length; i++) {
                var e = currentErrors[i];
                params += encodeURIComponent(e.message + ',' + e.source + ',' + e.line + '|');
            }
            currentErrors = [];

            post(urls.logErrors, params);
        },
        sendError: function (errorMessage, file, line) {
            var params = 'message=' + encodeURIComponent(errorMessage) + '&source=' + encodeURIComponent(file) + '&line=' + line + '&userAgent=' + encodeURIComponent(navigator.userAgent) + '&location=' + encodeURIComponent(self.location);
            post(urls.logError, params);
        },
        handle: function (e) {
            if (e) {
                //Note: Only Firefox and Safari support source file and line number in the exception object. Chrome and IE do not.
                //However, stack traces are way better and Firefox/Chrome/IE10+ support it. Use that instead!
                KbbErrorHandler.onerror(e.message || (e + ''), e.fileName || e.sourceURL, e.lineNumber || e.line, e);
            }
        }
    };
}());

window.onerror = KbbErrorHandler.onerror;
;
/* Add additional Modernizr tests to this file */

(function () {
    "use strict";

    // Mobile test last updated 2/21/2014
    // http://detectmobilebrowsers.com/      (javascript code to check for mobile devices)
    // http://detectmobilebrowsers.com/about (adding in tablet checking regex)
    Modernizr.addTest('mobile', function () { return (function (a) { return (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino|android|ipad|playbook|silk/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) })(navigator.userAgent || navigator.vendor || window.opera) });

    Modernizr.addTest('android', function () { return /Android/i.test(navigator.userAgent) });
    Modernizr.addTest('chrome', function () { return /Chrome/i.test(navigator.userAgent) });
    Modernizr.addTest('firefox', function () { return /Firefox/i.test(navigator.userAgent) });
    Modernizr.addTest('iemobile', function () { return /IEMobile/i.test(navigator.userAgent) });
    Modernizr.addTest('ie', function () { return /MSIE/i.test(navigator.userAgent) });
    Modernizr.addTest('ie10', function () { return /MSIE 10/i.test(navigator.userAgent) });
    Modernizr.addTest('ios', function () { return /iPhone|iPad|iPod/i.test(navigator.userAgent) });
    Modernizr.addTest('ios7', function () { return /(iPad|iPhone|iPod);.*CPU.*OS 7_\d/i.test(navigator.userAgent) });
    Modernizr.addTest('ios8', function () { return /(iPad|iPhone|iPod);.*CPU.*OS 8_\d/i.test(navigator.userAgent) });
    Modernizr.addTest('retina', function () { var ratio = "2.99/2"; var num = "1.499"; var mqs = ["only screen and (-moz-min-device-pixel-ratio:" + ratio + ")", "only screen and (-webkit-min-device-pixel-ratio:" + num + ")", "only screen and (min-device-pixel-ratio:" + num + ")"]; var isRetina = false; for (var i = mqs.length - 1; i >= 0; i--) { isRetina = Modernizr.mq(mqs[i]); if (isRetina) return isRetina } return isRetina });
    Modernizr.addTest('safari', function () { var userAgent = navigator.userAgent; return /Safari/i.test(userAgent) && !/Chrome/i.test(userAgent) && !/iPhone|iPad|iPod/i.test(userAgent) });
    Modernizr.addTest('pc', function () { return /Windows/i.test(navigator.userAgent) });
    Modernizr.addTest('mac', function () { return /Mac/i.test(navigator.userAgent) });
    Modernizr.addTest('silk', function () { return /Kindle|Silk/i.test(navigator.userAgent) });
    Modernizr.addTest('galaxytab2', function () { return /GT-P5113|GT-P3113/i.test(navigator.userAgent); });
})();
;
// Audience Segmentation in Omniture
KBB.create('KBB.AudienceSegment', function () {
    'use strict';

    var segment = [
        {
            name: 'assessment_owner',
            pagenames: [
                'condpricetisell',
                'optionstisell',
                'ymmtrimtisellovr_selltrade',
                'styletisell',
                'carworthhome',
                'cattisell',
                'compstylestisell',
                'printpage',
                'ymmtrimtisellspecs_selltrade',
                'ymmpathmodel_selltrade',
                'followcar_selltrade',
                'ymmpathmake_selltrade',
                'ymmpathmkcat_selltrade',
                'timkbbhome',
                'ymmtrimtisellconsrev_selltrade',
                'selltoolhome',
                'atcsellhome_selltrade_pp',
                'condquiztisell',
                'condrestisell',
                'gqselectvehicle',
                'gqselectvehicle_zip',
                'selltoolhome_zip',
                'selltoolkit_zip',
                'unfollowcar_selltrade',
                'selltoolkit',
                'selltoolkitsumm',
                'atcselladdphoto_selltrade-pp',
                'atcselladdpmt_selltrade-pp',
                'atcselladdrevvehdtl_selltrade-pp',
                'atcselladdthankt_selltrade-pp',
                'atcselladdvehaddtl_selltrade-pp',
                'atcselleditcontact_selltrade-pp',
                'atcselleditmain_selltrade-pp',
                'atcselleditphoto_selltrade-pp',
                'atcselleditpmt_selltrade-pp',
                'atcselleditrmv_selltrade-pp',
                'atcselleditvehdtl_selltrade-pp',
                'atcsellhome_selltrade-pp',
                'atcsellhome_selltrade-pp_zip',
                'atcsellpackage_selltrade-pp',
                'atcsellrevadlist_selltrade-pp',
                'atcsellsampad_selltrade-pp',
                'atcsellsampad_selltrade-pp_zip',
                'atcsellsignin_selltrade-pp',
                'cattisell_zip',
                'compstylestisell_zip',
                'condpricetisell_zip',
                'condquiztisell_zip',
                'condrestisell_zip',
                'condtisell',
                'followcar_selltrade_zip',
                'optionstisell_zip',
                'styletisell_zip',
                'timkbbhome_zip',
                'ymmpathmake_selltrade_zip',
                'ymmpathmodel_selltrade_zip',
                'ymmtrimtisellovr_selltrade_zip',
                'ymmtrimtisellspecs_selltrade_zip',
                'atcsellfaq',
                'atcsellfraud',
                'atcsellfraud_zip',
                'atcsellunpage'
            ]
        },
        {    
            name: 'assessment_nc',
            pagenames: [
                'optionsnew',
                'stylenew',
                'ymmtrimnewovr_buynew',
                'ymmpathmodel_buynew',
                'catnew',
                'dlrinfoinvovrnew',
                'compstylesbuynew',
                'ymmunknownovrnc_none',
                'dlrinfoinvmatchnew',
                'ymmpathmkcat_buynew',
                'ymmpathcat_buynew',
                'modalinvnew',
                'galmodalnew',
                'ymmtrimnewrank_buynew',
                'ymmpathmake_buynew',
                'ymmtrimnewspecs_buynew',
                'ymmtrimnewcostown_buynew',
                'ymmtrimnewexprev_buynew',
                'dlrinfoinvstorelotnew',
                'ymmpathmkcat_buynew_oem',
                'dlrinfoinvstorelotundefined',
                'ymmtrimnewconsrev_buynew',
                'ymmtrimnewrat_buynew',
                'ymmtrimnewincent_buynew',
                'ymmpathmake_buynew_oem',
                'classdetailnew',
                'ymmtrimnewgal_buynew',
                'classlistnew_dtlovr',
                'safetymain',
                'modalcostownnc',
                'costownmain',
                'gqleadform23',
                'ymmpathmkmdcat_buynew',
                'comparetechspecs',
                'comparefeatures',
                'compareoverview',
                'comparerevrat',
                'comparesafety',
                'comparehome',
                'exphome',
                'comparecustom',
                'compareintextphotos',
                'comparephotos',
                'comparevideo',
                'dlrinfoinvrevratnew',
                'dlrinfoinvspecialnew',
                'dlrinfoinvstorelot',
                'dlrinfoinvstorenew',
                'modalinv',
                'modalpmtcalc',
                'modalpmtcalcnew',
                'modalrealcknc',
                'ecommpartnerhome',
                'ecommpartnerhome_zip',
                'gqquotethank',
                'gqleadform23_zip',
                'makehub_toyot',
                'ecommpartnerhome',
                'gqquotethank',
                'modalinv',
                'modalpmtcalc',
                'modalpmtcalcnew',
                'modalrealcknc',
                'adv10buynew_zip',
                'catnew_zip',
                'compstylesbuynew_zip',
                'optionsnew_zip',
                'stylenew_zip',
                'ymmpathcat_buynew_zip',
                'ymmpathmake_buynew_oem_zip',
                'ymmpathmake_buynew_zip',
                'ymmpathmkcat_buynew_oem_zip',
                'ymmpathmkcat_buynew_zip',
                'ymmpathmodel_buynew_zip',
                'ymmtrimnewconsrev_buynew_zip',
                'ymmtrimnewcostown_buynew_zip',
                'ymmtrimnewexprev_buynew_zip',
                'ymmtrimnewgal_buynew_zip',
                'ymmtrimnewincent_buynew_zip',
                'ymmtrimnewovr_buynew_zip',
                'ymmtrimnewrank_buynew_zip',
                'ymmtrimnewrat_buynew_zip',
                'ymmtrimnewspecs_buynew_zip',
                'cashforclunkers',
                'comparecustom_zip',
                'comparehome_zip',
                'comparevideo_zip',
                'costownmain_zip',
                'dlrinfoinvmatch',
                'dlrinfoinvmatchnew_zip',
                'dlrinfoinvovrlistexpirednew',
                'dlrinfoinvovrlistrefinenew',
                'dlrinfoinvovrlisttabnew',
                'dlrinfoinvovrlisttabnew_zip',
                'dlrinfoinvovrmapviewtabnew',
                'dlrinfoinvovrnew_zip',
                'dlrinfoinvovrphotonew',
                'dlrinfoinvovrtabnew',
                'dlrinfoinvsocialnew',
                'dlrinfoinvspecial',
                'dlrinfoinvstorelot_zip',
                'dlrinfoinvstorelotnew_zip',
                'dlrinfoinvstorenew_zip',
                'exphome_zip'
            ]
        },
        {
            name: 'transact',
            pagenames: [ 
                'rtbdlrlist',
                'rtbdlrmap',
                'rtbhome',
                'classdetailnew',
                'classlistnew_dtlovr',
                'condpricebuyused',
                'optionsbuyused',
                'ymmtrimbuyusedovr_buyused',
                'stylebuyused',
                'uchome',
                'catbuyused',
                'compstylesbuyused',
                'uchomecpo',
                'classlistused',
                'classlistused_dtlovr',
                'ymmtrimbuyusedexprev_buyused',
                'ymmtrimbuyusedconsrev_buyused',
                'ymmtrimbuyusedgal_buyused',
                'ymmtrimbuyusedspecs_buyused',
                'classdetailused',
                'galmodalused',
                'ymmtrimbuyusedrat_buyused',
                'classlistused_dtlovr',
                'compareupsell',
                'classlistnew',
                'cpohome',
                'classbbvalueovrused',
                'classstorefrontnew',
                'classymmovrgalused',
                'classymmovrspecsused',
                'classmodelgroupused',
                'ymmtrimbuyusedcomp_buyused',
                'ymmpathmkcat_buyused',
                'ymmpathmodel_buyused',
                'ymmpathcat_buyused',
                'ymmpathmake_buyused',
                'searchresultsmodel',
                'ymmunknownovruc_none',
                'condquizbuyused',
                'condresbuyused',
                'classbbvalueovrcertified',
                'classbbvalueovrnew',
                'classdetailexpired',
                'classmodelgroupnew',
                'classsearch',
                'classstorefront',
                'classstorefrontused',
                'classymmovrconsrevnew',
                'classymmovrconsrevused',
                'classymmovrexprevnew',
                'classymmovrexprevused',
                'classymmovrgalnew',
                'classymmovrspecsnew',
                'modaloempromonew',
                'adv10buyused',
                'condresult',
                'cpoadvarticle',
                'cpoadvmain',
                'cpoinfocompare',
                'cpoinfoprograms',
                'dlrinfoinvstorelotcpo',
                'dlrinfoinvstorelotused',
                'modalinv',
                'modalinvcpo',
                'modalinvnew',
                'modalpmtcalc',
                'modalpmtcalcnew',
                'classbbvalueovrused_zip',
                'classdetailexpired_zip',
                'classdetailnew_photo',
                'classdetailnew_zip',
                'classdetailused_photo',
                'classdetailused_zip',
                'classlistnew_zip',
                'classlistused_zip',
                'classsaved',
                'classsearch_color',
                'classsearch_doors',
                'classsearch_drivetrain',
                'classsearch_engine',
                'classsearch_fueltype',
                'classsearch_intent',
                'classsearch_mkmd',
                'classsearch_sellertype',
                'classsearch_trans',
                'classsearch_vehtype',
                'classsearch_zip',
                'classymmovrexprevused_zip',
                'classymmovrspecsused_zip',
                'adv10buyused_zip',
                'catbuyused_zip',
                'compstylesbuyused_zip',
                'condpricebuyused_zip',
                'optionsbuyused_zip',
                'stylebuyused_zip',
                'ymmpathcat_buyused_zip',
                'ymmpathmake_buyused_zip',
                'ymmpathmkcat_buyused_zip',
                'ymmpathmodel_buyused_zip',
                'ymmtrimbuyusedcomp_buyused_zip',
                'ymmtrimbuyusedconsrev_buyused_zip',
                'ymmtrimbuyusedexprev_buyused_zip',
                'ymmtrimbuyusedgal_buyused_zip',
                'ymmtrimbuyusedovr_buyused_zip',
                'ymmtrimbuyusedrat_buyused_zip',
                'ymmtrimbuyusedspecs_buyused_zip',
                'condresult_zip',
                'cpoadvarticle_zip',
                'cpohome_zip',
                'dlrinfoinvovrlistrefineused',
                'dlrinfoinvovrlisttabused',
                'dlrinfoinvovrlisttabused_zip',
                'dlrinfoinvovrmapviewtabused',
                'dlrinfoinvovrtabused',
                'dlrinfoinvovrused',
                'dlrinfoinvovrused_zip',
                'dlrinfoinvrevratused',
                'dlrinfoinvstorelotcpo_zip',
                'dlrinfoinvstorelotnew|certified',
                'dlrinfoinvstorelotnew|used',
                'dlrinfoinvstorelotnew|used|certified',
                'dlrinfoinvstorelotused_zip',
                'dlrinfoinvstorelotused|certified',
                'dlrinfoinvstoreused'
            ]
        },
        {
            name: 'knowledge',
            pagenames: [
                'awardsresale_2015',
                'lns',
                'top10listovrnew',
                'top10listnumnew',
                'top10listsumnew',
                'top10listnumused',
                'top10listhome',
                'top10listovrused',
                'revrathome',
                'awardscostown_2015',
                'top10listsumused',
                'lnc',
                'mediagal360ext',
                'mediagal360int',
                'mediagalcolorschart',
                'mediagalcolorsext',
                'mediagalcolorsint',
                'mediagalhistory',
                'mediagalhome',
                'mediagalphotoall',
                'mediagalphotoext',
                'mediagalphotoint',
                'mediagalphotoovrfull',
                'mediagalvideo',
                'mykbbacctset',
                'mykbbchngpw',
                'mykbbcreateacct',
                'mykbbfrgtpw',
                'mykbbrcntclrd',
                'mykbbrcnt',
                'mykbbrcntnew',
                'mykbbrcntused',
                'mykbbsaveclrd',
                'mykbbsavecomp',
                'mykbbsave',
                'mykbbsaveused',
                'mykbbsignin',
                'mykbbtermsuse',
                'ovncchangefnc',
                'ncshopmain',
                'realckmain',
                'revmain',
                'revpromodel',
                'seoinvlandingpathmain',
                'ymmpathcat_none',
                'ymmpathmake_none',
                'ymmpathmake_none_oem',
                'ymmpathmkcat_none',
                'ymmpathmkcat_none_oem',
                'ymmpathmodel_none',
                'adv10buynew',
                'adv0finance',
                'adv10sell',
                'adv6finance',
                'advadtips',
                'advalladvice',
                'advallbuying',
                'advcarcare',
                'advcarsins',
                'advcolor',
                'advdestchg',
                'advfiveins',
                'advhome',
                'advhowmuch',
                'advinjflush',
                'advkbbprice',
                'advpremgas',
                'advrecalls',
                'advsaveins',
                'advstick',
                'advsuvdil',
                'advupdown',
                'advwheel',
                'adv0finance_zip',
                'adv10sell_zip',
                'advadtips_zip',
                'advalladvice_zip',
                'advallbuying_zip',
                'advarticle',
                'advbrkswork',
                'advbuyvlease',
                'advcarcare_zip',
                'advcarsins_zip',
                'advcolor_zip',
                'advcondquiz',
                'advcostown',
                'advcred',
                'advcvjoints',
                'advdestchg_zip',
                'advfaketitle',
                'advfaketitle_zip',
                'advfiveins_zip',
                'advfmlyvehawrd',
                'advfraud',
                'advhowmuch_zip',
                'advinjflush_zip',
                'advkeep',
                'advmoldy',
                'advmoldy_zip',
                'advpit',
                'advpit_zip',
                'advplastic',
                'advpremgas_zip',
                'advproeng',
                'advproeng_zip',
                'advrebeng',
                'advrecalls_zip',
                'advrightins',
                'advrightins_zip',
                'advsaveins_zip',
                'advscooter',
                'advscooter_zip',
                'advseas',
                'advseas_zip',
                'advspngbrks',
                'advstick_zip',
                'advsuvdil_zip',
                'advtimbelt',
                'advtiresrtd',
                'advtruefin',
                'advtruefin_zip',
                'advupdown_zip',
                'advvalue',
                'advweld',
                'advwheel_zip',
                'asc',
                'awardsbrandimg_2015',
                'awardsbrandimg_2015_zip',
                'awardscostown_2014',
                'awardscostown_2014_zip',
                'awardscostown_2015_zip',
                'awardsresale',
                'awardsresale_2012',
                'awardsresale_2012_zip',
                'awardsresale_2013',
                'awardsresale_2013_zip',
                'awardsresale_2014',
                'awardsresale_2014_zip',
                'awardsresale_2015_zip',
                'mediagal360ext_zip',
                'mediagal360int_zip',
                'mediagalcolorschart_zip',
                'mediagalcolorsext_zip',
                'mediagalcolorsint_zip',
                'mediagalcompare',
                'mediagalcompare_zip',
                'mediagalhistory_zip',
                'mediagalhome_zip',
                'mediagalphotoall_zip',
                'mediagalphotoext_zip',
                'mediagalphotoint_zip',
                'mediagalphotoovrfull_zip',
                'mediagalvideo_zip',
                'mktplacehome',
                'modalincentovrly',
                'modalinvcpo',
                'modalinvused',
                'modalpmtcalccpo',
                'modalpmtcalcused',
                'modalrealcknc_zip',
                'modalrevratnc',
                'modalrevratnc_zip',
                'modalvidbuyguide',
                'mykbblike',
                'mykbblikenew',
                'mykbbrcntclrd_zip',
                'mykbbrcntused_zip',
                'mykbbsaveclrd_zip',
                'mykbbsavecomp_zip',
                'mykbbsavefdpq',
                'mykbbsavefdpq_zip',
                'mykbbsavenew',
                'mykbbsavenew_zip',
                'mykbbsaveused_zip',
                'mykbbtermsuse_zip',
                'mykbbtop',
                'mykbbtopnew',
                'mykbbtopused',
                'mykbbwelcome',
                'realckmain_zip',
                'revrathome_zip',
                'rtbdlrlist_zip',
                'safetymain_zip',
                'safetyold',
                'safetyrecall',
                'safetyrecall_zip',
                'safetysci',
                'safetysss',
                'safetytire',
                'top10listhome_zip',
                'top10listnumnew_zip',
                'top10listnumused_zip',
                'top10listovrnew_zip',
                'top10listovrused_zip',
                'top10listsumnew_zip',
                'top10listsumused_zip',
                'ymmpathcat_none_zip',
                'ymmpathmake_none_zip',
                'ymmpathmkcat_none_zip',
                'ymmpathmodel_none_zip',
                'ymmunknownovrnc_none_zip'
            ]
        }
    ];

    var getSegment = function (omniturePagename) {
        var i;
        var pageName = (omniturePagename === null || omniturePagename === '') ? KBB.Page.getDataLayer().omniture.pagename : omniturePagename;

        if (pageName.indexOf('awards') > -1) {
            return 'knowledge';
        }

        for (i = 0; i < segment.length; i++) {
            if (segment[i].pagenames.indexOf(pageName) > -1) {
                return segment[i].name.toLowerCase();
            }
        }

        return 'other';
    };

    return {
        getSegment: getSegment
    };
});
;
KBB.Page.setPartnerMappings({
    'demopartner': 'dp',
    'demopartner_test': 'dpt',
    'loan': 'suntrst',
    'vehicleHistoryReport': 'autock',
    'warranty': 'warrantydirect',
    'insurance': 'geico',
    'classifiedsClassic': 'atcatx',
    'instantCashOffer': 'buybook',
    'classifieds': 'atcclass',
    'creditReport': 'experian',
    'dealerRatings': 'dlrrater',
    'motorcycleclassifieds': 'atcdow',
    'ncleads': 'ncleadgen',
    'atcsell': 'atcsell'
});
;
KBB.Page.setReferrerTrackingIdMappings({
    '1': '1-direct',
    '2': '2-yahoopaid',
    '3': '3-googlepaid',
    '4': '4-msnpaid',
    '5': '5-yahooinclusion',
    '13': '13-googlepaid_contentmatch',
    '14': '14-yahoopaid_contentmatch',
    '15': '15-yahoopaid_local',
    '16': '16-yahoopaid_premiumcatauto',
    '17': '17-yahoopaid_frontpagebt',
    '18': '18-yahoopaid_searchsubmit',
    '19': '19-googlepaid_generalcars',
    '20': '20-googlepaid_trademark',
    '21': '21-googlepaid_categories',
    '22': '22-googlepaid_make',
    '23': '23-googlepaid_model',
    '24': '24-googlepaid_quote',
    '25': '25-googlepaid_geotargetquote',
    '26': '26-googlepaid_competitors',
    '27': '27-google_ppa_ncquote',
    '28': '28-yahoopaid_generalcars',
    '29': '29-yahoopaid_trademark',
    '30': '30-yahoopaid_categories',
    '31': '31-yahoopaid_make',
    '32': '32-yahoopaid_model',
    '33': '33-yahoopaid_quote',
    '34': '34-yahoopaid_competitors',
    '35': '35-askpaid',
    '36': '36-rss',
    '37': '37-emailpage',
    '38': '38-quigo_paid_inclusion_yahoo',
    '39': '39-search_syndication',
    '40': '40-referred',
    '100': '100-deal-reynolds',
    '101': '101-deal-bzresults',
    '1000': '1000-askroc'
});
;
KBB.Page.setReferrerTrackingDomainMappings({
    'search.yahoo.com': '6-yahooNatural',
    'www.google.com': '7-googleNatural',
    'google.com': '7-googleNatural',
    'search.msn.com': '8-MSNnatural',
    'search.live.com': '8-MSNnatural',
    'search.comcast.net': '9-CNETnatural',
    'www.ask.com': '10-askNatural',
    'ask.com': '10-askNatural',
    'search.ask.com': '10-askNatural',
    'aolsearch.aol.com': '11-AOLnatural',
    'search.aol.com': '11-AOLnatural'
});;
/* SiteCatalyst code version: H.22.1.
Copyright 1996-2010 Adobe, Inc. All Rights Reserved
More info available at http://www.omniture.com */
/************************ ADDITIONAL FEATURES ************************
     Plugins
*/

//var s_account="kbbmain"
var s=s_gi(s_account)
/************************** CONFIG SECTION **************************/
/* You may add or alter any code config here. */
s.charSet = "ISO-8859-1"
s.visitorNamespace = "kelleybluebook"
/* Conversion Config */
s.currencyCode="USD"
/* Link Tracking Config */
s.trackDownloadLinks=true
s.trackExternalLinks=true
s.trackInlineStats=true
s.linkDownloadFileTypes="exe,zip,wav,mp3,mov,mpg,avi,wmv,pdf,doc,docx,xls,xlsx,ppt,pptx"
s.linkInternalFilters = "javascript:,kbb.com,kelleybluebookimages.com,209.67.183.,66.209.70."
s.linkLeaveQueryString=false
s.linkTrackVars = "server,zip,prop2,prop4,prop26,prop27,prop28,prop18,eVar2,products,events,purchaseID,prop39,prop41,prop17";
s.linkTrackEvents = "purchase";
/* Plugin Config */
s.usePlugins=true

function s_doPlugins(s) {
	/* Add calls to plugins here */
	
	s.campaign=s.getQueryParam('scid');
	s.eVar9 = s.getQueryParam("shout_id");
    /* Flash Detection - Set eVar46 only on first page of visit */
    s.detectRIA('', 'eVar46', '', '', '', '1');

    /* facebookSocialPlugin v1.1 - Stop FB Referrer Inflation */
    s.referrer = s.facebookSocialRefferrers();

    /*socialPlatforms v1.0 - used for SocialAnalytics*/
    s.socialPlatforms('eVar18');

    /* Copy props to eVars */
    if (s.prop41 && !s.eVar19) s.eVar19 = "D=c41"; //copy session id to evar19
    if (s.prop17) s.eVar24 = "D=c17"; //copy page instance to evar24
}
s.doPlugins=s_doPlugins;

/************************** PLUGINS SECTION *************************/
/* You may insert any plugins you wish to use here.                 */

/*
 * Plugin: getQueryParam 2.3
 */
s.getQueryParam=new Function("p","d","u",""
+"var s=this,v='',i,t;d=d?d:'';u=u?u:(s.pageURL?s.pageURL:s.wd.locati"
+"on);if(u=='f')u=s.gtfs().location;while(p){i=p.indexOf(',');i=i<0?p"
+".length:i;t=s.p_gpv(p.substring(0,i),u+'');if(t){t=t.indexOf('#')>-"
+"1?t.substring(0,t.indexOf('#')):t;}if(t)v+=v?d+t:t;p=p.substring(i="
+"=p.length?i:i+1)}return v");
s.p_gpv=new Function("k","u",""
+"var s=this,v='',i=u.indexOf('?'),q;if(k&&i>-1){q=u.substring(i+1);v"
+"=s.pt(q,'&','p_gvf',k)}return v");
s.p_gvf=new Function("t","k",""
+"if(t){var s=this,i=t.indexOf('='),p=i<0?t:t.substring(0,i),v=i<0?'T"
+"rue':t.substring(i+1);if(p.toLowerCase()==k.toLowerCase())return s."
+"epa(v)}return ''");

/*
* Utility Function: split v1.5 (JS 1.0 compatible)
*/
s.split = new Function("l", "d", ""
+ "var i,x=0,a=new Array;while(l){i=l.indexOf(d);i=i>-1?i:l.length;a[x"
+ "++]=l.substring(0,i);l=l.substring(i+d.length);}return a");
/*
* Plugin: detectRIA v0.1 - detect and set Flash, Silverlight versions
*/
s.detectRIA = new Function("cn", "fp", "sp", "mfv", "msv", "sf", ""
+ "cn=cn?cn:'s_ria';msv=msv?msv:2;mfv=mfv?mfv:10;var s=this,sv='',fv=-"
+ "1,dwi=0,fr='',sr='',w,mt=s.n.mimeTypes,uk=s.c_r(cn),k=s.c_w('s_cc',"
+ "'true',0)?'Y':'N';fk=uk.substring(0,uk.indexOf('|'));sk=uk.substrin"
+ "g(uk.indexOf('|')+1,uk.length);if(k=='Y'&&s.p_fo('detectRIA')){if(u"
+ "k&&!sf){if(fp){s[fp]=fk;}if(sp){s[sp]=sk;}return false;}if(!fk&&fp)"
+ "{if(s.pl&&s.pl.length){if(s.pl['Shockwave Flash 2.0'])fv=2;x=s.pl['"
+ "Shockwave Flash'];if(x){fv=0;z=x.description;if(z)fv=z.substring(16"
+ ",z.indexOf('.'));}}else if(navigator.plugins&&navigator.plugins.len"
+ "gth){x=navigator.plugins['Shockwave Flash'];if(x){fv=0;z=x.descript"
+ "ion;if(z)fv=z.substring(16,z.indexOf('.'));}}else if(mt&&mt.length)"
+ "{x=mt['application/x-shockwave-flash'];if(x&&x.enabledPlugin)fv=0;}"
+ "if(fv<=0)dwi=1;w=s.u.indexOf('Win')!=-1?1:0;if(dwi&&s.isie&&w&&exec"
+ "Script){result=false;for(var i=mfv;i>=3&&result!=true;i--){execScri"
+ "pt('on error resume next: result = IsObject(CreateObject(\"Shockwav"
+ "eFlash.ShockwaveFlash.'+i+'\"))','VBScript');fv=i;}}fr=fv==-1?'flas"
+ "h not detected':fv==0?'flash enabled (no version)':'flash '+fv;}if("
+ "!sk&&sp&&s.apv>=4.1){var tc='try{x=new ActiveXObject(\"AgControl.A'"
+ "+'gControl\");for(var i=msv;i>0;i--){for(var j=9;j>=0;j--){if(x.is'"
+ "+'VersionSupported(i+\".\"+j)){sv=i+\".\"+j;break;}}if(sv){break;}'"
+ "+'}}catch(e){try{x=navigator.plugins[\"Silverlight Plug-In\"];sv=x'"
+ "+'.description.substring(0,x.description.indexOf(\".\")+2);}catch('"
+ "+'e){}}';eval(tc);sr=sv==''?'silverlight not detected':'silverlight"
+ " '+sv;}if((fr&&fp)||(sr&&sp)){s.c_w(cn,fr+'|'+sr,0);if(fr)s[fp]=fr;"
+ "if(sr)s[sp]=sr;}}");
s.p_fo = new Function("n", ""
+ "var s=this;if(!s.__fo){s.__fo=new Object;}if(!s.__fo[n]){s.__fo[n]="
+ "new Object;return 1;}else {return 0;}");
/*
* facebookSocialPlugin v1.1 - stopping the referrer inflation
*/
s.facebookSocialRefferrers = new Function("c", ""
+ "var s=this,g,i,j,m,v,d,x,J,n=new Date;n.setTime(n.getTime()+1800000"
+ ");c=c?c:'s_fbsr';if(s.c_r(c)){J=0}if(!s.c_w(c,1,n)){s.c_w(c,1,0)}if"
+ "(!s.c_r(c)){J=0}x=g=s.referrer?s.referrer:document.referrer;if(J==0"
+ "){g=g.toLowerCase();if(g){z=g.indexOf('?');i=z>-1?z:g.length;j=g.su"
+ "bstring(0,i);v=j.indexOf('facebook.com')>-1?1:'';if(v){f=s.getQuery"
+ "Param('u','',g);if(f){d=s.linkInternalFilters.toLowerCase();d=s.spl"
+ "it(d,',');b=d.length;for(c=0;c<b;c++){m=f.indexOf(d[c])>-1?1:'';if("
+ "m)x=d[1];}}}}}return x");

/*
* Plugin: socialPlatforms v1.1
*/
s.socialPlatforms = new Function("a", ""
+ "var s=this,g,K,D,E,F,i;g=s.referrer?s.referrer:document.referrer;g=g."
+ "toLowerCase();K=s.split(s.socPlatList,'|');for(i=0;i<K.length;i++){"
+ "D=s.split(K[i],'>');if(g.indexOf(D[0])!=-1){if(a){s[a]=D[1];}}}");

s.socPlatList = "facebook.com>Facebook|twitter.com>Twitter|t.co/>Twitter|youtube.com>Youtube|clipmarks.com>Clipmarks|dailymotion.com>Dailymotion|delicious.com>Delicious|digg.com>Digg|diigo.com>Diigo|flickr.com>Flickr|flixster.com>Flixster|fotolog.com>Fotolog|friendfeed.com>FriendFeed|google.com/buzz>Google Buzz|buzz.googleapis.com>Google Buzz|plus.google.com>Google+|hulu.com>Hulu|identi.ca>identi.ca|ilike.com>iLike|intensedebate.com>IntenseDebate|myspace.com>MySpace|newsgator.com>Newsgator|photobucket.com>Photobucket|plurk.com>Plurk|slideshare.net>SlideShare|smugmug.com>SmugMug|stumbleupon.com>StumbleUpon|tumblr.com>Tumblr|vimeo.com>Vimeo|wordpress.com>WordPress|xanga.com>Xanga|metacafe.com>Metacafe|pinterest.com>Pinterest";

/*  
 * socialAuthors v1.5.2
 */
s.socialAuthors = new Function("", ""
+ "var s=this,g;g=s.referrer?s.referrer:document.referrer;if(g.indexOf"
+ "('http://t.co/')===0||g.indexOf('https://t.co/')===0||g.indexOf('pi"
+ "nterest.com/pin')!==-1||g.indexOf('tumblr.com')!==-1||g.indexOf('yo"
+ "utube.com')!==-1){s.Integrate.add('SocialAuthor');s.Integrate.Socia"
+ "lAuthor.tEvar='eVar30';s.Integrate.SocialAuthor.get('http://sa-se"
+ "rvices.social.omniture.com/author/name?var=[VAR]&callback=s.socialA"
+ "uthorSearch&rs='+encodeURIComponent(s_account)+'&q='+encodeURICompo"
+ "nent(g));s.Integrate.SocialAuthor.delay();s.Integrate.SocialAuthor."
+ "setVars=function(s,p){if(p.tEvar==='reserved'){s.contextData['a.soc"
+ "ialauthor']=s.user;}else{s[p.tEvar]=s.user;}}}");
s.socialAuthorSearch = new Function("obj", ""
+ "var s=this;if(typeof obj==='undefined'||typeof obj.author==='undefi"
+ "ned'){s.user='Not Found';}else{s.user=obj.author;}s.Integrate.Socia"
+ "lAuthor.ready();");

/* Configure Modules and Plugins */

/*********Media Module Calls**************/
s.loadModule("Media");
s.Media.autoTrack = true;
s.Media.trackWhilePlaying = true;
s.Media.trackVars = "pageName,server,channel,zip,prop1,prop2,prop3,prop4,prop11,prop12,prop13,prop14,prop16,prop21,prop23,prop24,prop26,prop27,prop28,prop29,prop30,prop31,prop32,prop34,eVar1,eVar5";  //Enter the variables to be sent with Adobe Web beacons
s.Media.trackEvents = "";  //Enter the events to be sent with Adobe Web beacons
s.Media.trackMilestones = "25,50,75";  //could also use s.Media.trackSeconds, if desired

s.maxDelay = '3000'; //max time to wait for 3rd party api response in milliseconds
s.loadModule("Integrate");
s.Integrate.onLoad = function (s, m) {
    s.socialAuthors();
    //add other integration module dependent functions here
};

/* WARNING: Changing any of the below variables will cause drastic
changes to how your visitor data is collected.  Changes should only be
made when instructed to do so by your account manager.*/
s.trackingServer="metrics.kbb.com"
s.trackingServerSecure="smetrics.kbb.com"

/****************************** MODULES *****************************/
/* Module: Media */
s.m_Media_c="var m=s.m_i('Media');m.cn=function(n){var m=this;return m.s.rep(m.s.rep(m.s.rep(n,\"\\n\",''),\"\\r\",''),'--**--','')};m.open=function(n,l,p,b){var m=this,i=new Object,tm=new Date,a='',"
+"x;n=m.cn(n);l=parseInt(l);if(!l)l=1;if(n&&p){if(!m.l)m.l=new Object;if(m.l[n])m.close(n);if(b&&b.id)a=b.id;for (x in m.l)if(m.l[x]&&m.l[x].a==a)m.close(m.l[x].n);i.n=n;i.l=l;i.p=m.cn(p);i.a=a;i.t=0"
+";i.ts=0;i.s=Math.floor(tm.getTime()/1000);i.lx=0;i.lt=i.s;i.lo=0;i.e='';i.to=-1;m.l[n]=i}};m.close=function(n){this.e(n,0,-1)};m.play=function(n,o){var m=this,i;i=m.e(n,1,o);i.m=new Function('var m"
+"=s_c_il['+m._in+'],i;if(m.l){i=m.l[\"'+m.s.rep(i.n,'\"','\\\\\"')+'\"];if(i){if(i.lx==1)m.e(i.n,3,-1);i.mt=setTimeout(i.m,5000)}}');i.m()};m.stop=function(n,o){this.e(n,2,o)};m.track=function(n){va"
+"r m=this;if (m.trackWhilePlaying) {m.e(n,4,-1)}};m.e=function(n,x,o){var m=this,i,tm=new Date,ts=Math.floor(tm.getTime()/1000),ti=m.trackSeconds,tp=m.trackMilestones,z=new Array,j,d='--**--',t=1,b,"
+"v=m.trackVars,e=m.trackEvents,pe='media',pev3,w=new Object,vo=new Object;n=m.cn(n);i=n&&m.l&&m.l[n]?m.l[n]:0;if(i){w.name=n;w.length=i.l;w.playerName=i.p;if(i.to<0)w.event=\"OPEN\";else w.event=(x="
+"=1?\"PLAY\":(x==2?\"STOP\":(x==3?\"MONITOR\":\"CLOSE\")));w.openTime=new Date();w.openTime.setTime(i.s*1000);if(x>2||(x!=i.lx&&(x!=2||i.lx==1))) {b=\"Media.\"+name;pev3 = m.s.ape(i.n)+d+i.l+d+m.s.a"
+"pe(i.p)+d;if(x){if(o<0&&i.lt>0){o=(ts-i.lt)+i.lo;o=o<i.l?o:i.l-1}o=Math.floor(o);if(x>=2&&i.lo<o){i.t+=o-i.lo;i.ts+=o-i.lo;}if(x<=2){i.e+=(x==1?'S':'E')+o;i.lx=x;}else if(i.lx!=1)m.e(n,1,o);i.lt=ts"
+";i.lo=o;pev3+=i.t+d+i.s+d+(m.trackWhilePlaying&&i.to>=0?'L'+i.to:'')+i.e+(x!=2?(m.trackWhilePlaying?'L':'E')+o:'');if(m.trackWhilePlaying){b=0;pe='m_o';if(x!=4){w.offset=o;w.percent=((w.offset+1)/w"
+".length)*100;w.percent=w.percent>100?100:Math.floor(w.percent);w.timePlayed=i.t;if(m.monitor)m.monitor(m.s,w)}if(i.to<0)pe='m_s';else if(x==4)pe='m_i';else{t=0;v=e='None';ti=ti?parseInt(ti):0;z=tp?"
+"m.s.sp(tp,','):0;if(ti&&i.ts>=ti)t=1;else if(z){if(o<i.to)i.to=o;else{for(j=0;j<z.length;j++){ti=z[j]?parseInt(z[j]):0;if(ti&&((i.to+1)/i.l<ti/100)&&((o+1)/i.l>=ti/100)){t=1;j=z.length}}}}}}}else{m"
+".e(n,2,-1);if(m.trackWhilePlaying){w.offset=i.lo;w.percent=((w.offset+1)/w.length)*100;w.percent=w.percent>100?100:Math.floor(w.percent);w.timePlayed=i.t;if(m.monitor)m.monitor(m.s,w)}m.l[n]=0;if(i"
+".e){pev3+=i.t+d+i.s+d+(m.trackWhilePlaying&&i.to>=0?'L'+i.to:'')+i.e;if(m.trackWhilePlaying){v=e='None';pe='m_o'}else{t=0;m.s.fbr(b)}}else t=0;b=0}if(t){vo.linkTrackVars=v;vo.linkTrackEvents=e;vo.p"
+"e=pe;vo.pev3=pev3;m.s.t(vo,b);if(m.trackWhilePlaying){i.ts=0;i.to=o;i.e=''}}}}return i};m.ae=function(n,l,p,x,o,b){if(n&&p){var m=this;if(!m.l||!m.l[n])m.open(n,l,p,b);m.e(n,x,o)}};m.a=function(o,t"
+"){var m=this,i=o.id?o.id:o.name,n=o.name,p=0,v,c,c1,c2,xc=m.s.h,x,e,f1,f2='s_media_'+m._in+'_oc',f3='s_media_'+m._in+'_t',f4='s_media_'+m._in+'_s',f5='s_media_'+m._in+'_l',f6='s_media_'+m._in+'_m',"
+"f7='s_media_'+m._in+'_c',tcf,w;if(!i){if(!m.c)m.c=0;i='s_media_'+m._in+'_'+m.c;m.c++}if(!o.id)o.id=i;if(!o.name)o.name=n=i;if(!m.ol)m.ol=new Object;if(m.ol[i])return;m.ol[i]=o;if(!xc)xc=m.s.b;tcf=n"
+"ew Function('o','var e,p=0;try{if(o.versionInfo&&o.currentMedia&&o.controls)p=1}catch(e){p=0}return p');p=tcf(o);if(!p){tcf=new Function('o','var e,p=0,t;try{t=o.GetQuickTimeVersion();if(t)p=2}catc"
+"h(e){p=0}return p');p=tcf(o);if(!p){tcf=new Function('o','var e,p=0,t;try{t=o.GetVersionInfo();if(t)p=3}catch(e){p=0}return p');p=tcf(o)}}v=\"var m=s_c_il[\"+m._in+\"],o=m.ol['\"+i+\"']\";if(p==1){"
+"p='Windows Media Player '+o.versionInfo;c1=v+',n,p,l,x=-1,cm,c,mn;if(o){cm=o.currentMedia;c=o.controls;if(cm&&c){mn=cm.name?cm.name:c.URL;l=cm.duration;p=c.currentPosition;n=o.playState;if(n){if(n="
+"=8)x=0;if(n==3)x=1;if(n==1||n==2||n==4||n==5||n==6)x=2;}';c2='if(x>=0)m.ae(mn,l,\"'+p+'\",x,x!=2?p:-1,o)}}';c=c1+c2;if(m.s.isie&&xc){x=m.s.d.createElement('script');x.language='jscript';x.type='tex"
+"t/javascript';x.htmlFor=i;x.event='PlayStateChange(NewState)';x.defer=true;x.text=c;xc.appendChild(x);o[f6]=new Function(c1+'if(n==3){x=3;'+c2+'}setTimeout(o.'+f6+',5000)');o[f6]()}}if(p==2){p='Qui"
+"ckTime Player '+(o.GetIsQuickTimeRegistered()?'Pro ':'')+o.GetQuickTimeVersion();f1=f2;c=v+',n,x,t,l,p,p2,mn;if(o){mn=o.GetMovieName()?o.GetMovieName():o.GetURL();n=o.GetRate();t=o.GetTimeScale();l"
+"=o.GetDuration()/t;p=o.GetTime()/t;p2=o.'+f5+';if(n!=o.'+f4+'||p<p2||p-p2>5){x=2;if(n!=0)x=1;else if(p>=l)x=0;if(p<p2||p-p2>5)m.ae(mn,l,\"'+p+'\",2,p2,o);m.ae(mn,l,\"'+p+'\",x,x!=2?p:-1,o)}if(n>0&&"
+"o.'+f7+'>=10){m.ae(mn,l,\"'+p+'\",3,p,o);o.'+f7+'=0}o.'+f7+'++;o.'+f4+'=n;o.'+f5+'=p;setTimeout(\"'+v+';o.'+f2+'(0,0)\",500)}';o[f1]=new Function('a','b',c);o[f4]=-1;o[f7]=0;o[f1](0,0)}if(p==3){p='"
+"RealPlayer '+o.GetVersionInfo();f1=n+'_OnPlayStateChange';c1=v+',n,x=-1,l,p,mn;if(o){mn=o.GetTitle()?o.GetTitle():o.GetSource();n=o.GetPlayState();l=o.GetLength()/1000;p=o.GetPosition()/1000;if(n!="
+"o.'+f4+'){if(n==3)x=1;if(n==0||n==2||n==4||n==5)x=2;if(n==0&&(p>=l||p==0))x=0;if(x>=0)m.ae(mn,l,\"'+p+'\",x,x!=2?p:-1,o)}if(n==3&&(o.'+f7+'>=10||!o.'+f3+')){m.ae(mn,l,\"'+p+'\",3,p,o);o.'+f7+'=0}o."
+"'+f7+'++;o.'+f4+'=n;';c2='if(o.'+f2+')o.'+f2+'(o,n)}';if(m.s.wd[f1])o[f2]=m.s.wd[f1];m.s.wd[f1]=new Function('a','b',c1+c2);o[f1]=new Function('a','b',c1+'setTimeout(\"'+v+';o.'+f1+'(0,0)\",o.'+f3+"
+"'?500:5000);'+c2);o[f4]=-1;if(m.s.isie)o[f3]=1;o[f7]=0;o[f1](0,0)}};m.as=new Function('e','var m=s_c_il['+m._in+'],l,n;if(m.autoTrack&&m.s.d.getElementsByTagName){l=m.s.d.getElementsByTagName(m.s.i"
+"sie?\"OBJECT\":\"EMBED\");if(l)for(n=0;n<l.length;n++)m.a(l[n]);}');if(s.wd.attachEvent)s.wd.attachEvent('onload',m.as);else if(s.wd.addEventListener)s.wd.addEventListener('load',m.as,false)";
s.m_i("Media");

/* Module: Integrate */
s.m_Integrate_c = "var m=s.m_i('Integrate');m.add=function(n,o){var m=this,p;if(!o)o='s_Integrate_'+n;if(!m.s.wd[o])m.s.wd[o]=new Object;m[n]=new Object;p=m[n];p._n=n;p._m=m;p._c=0;p._d=0;p.disable=0;p"
+ ".get=m.get;p.delay=m.delay;p.ready=m.ready;p.beacon=m.beacon;p.script=m.script;m.l[m.l.length]=n};m._g=function(t){var m=this,s=m.s,i,p,f=(t?'use':'set')+'Vars',tcf;for(i=0;i<m.l.length;i++){p=m[m."
+ "l[i]];if(p&&!p.disable&&p[f]){if(s.apv>=5&&(!s.isopera||s.apv>=7)){tcf=new Function('s','p','f','var e;try{p[f](s,p)}catch(e){}');tcf(s,p,f)}else p[f](s,p)}}};m._t=function(){this._g(1)};m._fu=func"
+ "tion(p,u){var m=this,s=m.s,v,x,y,z,tm=new Date;if(u.toLowerCase().substring(0,4) != 'http')u='http://'+u;if(s.ssl)u=s.rep(u,'http:','https:');p.RAND=Math&&Math.random?Math.floor(Math.random()*10000"
+ "000000000):tm.getTime();p.RAND+=Math.floor(tm.getTime()/10800000)%10;x=0;while(x>=0){x=u.indexOf('[',x);if(x>=0){y=u.indexOf(']',x);if(y>x){z=u.substring(x+1,y);if(z.length>2&&z.substring(0,2)=='s."
+ "'){v=s[z.substring(2)];if(!v)v=''}else{v=''+p[z];if(!(v==p[z]||parseFloat(v)==p[z]))z=0}if(z) {u=u.substring(0,x)+s.rep(escape(v),'+','%2B')+u.substring(y+1);x=y-(z.length-v.length+1)} else {x=y}}}"
+ "}return u};m.get=function(u,v){var p=this,m=p._m;if(!p.disable){if(!v)v='s_'+m._in+'_Integrate_'+p._n+'_get_'+p._c;p._c++;p.VAR=v;p._d++;m.s.loadModule('Integrate:'+v,m._fu(p,u),0,1,p._n)}};m.delay"
+ "=function(){var p=this;if(p._d<=0)p._d=1};m.ready=function(){var p=this,m=p._m;p._d=0;if(!p.disable)m.s.dlt()};m._d=function(){var m=this,i,p;for(i=0;i<m.l.length;i++){p=m[m.l[i]];if(p&&!p.disable&"
+ "&p._d>0)return 1}return 0};m._x=function(d,n){var p=this[n],x;if(!p.disable){for(x in d)if(x&&(!Object||!Object.prototype||!Object.prototype[x]))p[x]=d[x];p._d--}};m.beacon=function(u){var p=this,m"
+ "=p._m,s=m.s,imn='s_i_'+m._in+'_Integrate_'+p._n+'_'+p._c,im;if(!p.disable&&s.d.images&&s.apv>=3&&(!s.isopera||s.apv>=7)&&(s.ns6<0||s.apv>=6.1)){p._c++;im=s.wd[imn]=new Image;im.src=m._fu(p,u)}};m.s"
+ "cript=function(u){var p=this,m=p._m;if(!p.disable)m.s.loadModule(0,m._fu(p,u),0,1)};m.l=new Array;if(m.onLoad)m.onLoad(s,m)";
s.m_i("Integrate");

/************* DO NOT ALTER ANYTHING BELOW THIS LINE ! **************/
var s_code = '', s_objectID; function s_gi(un, pg, ss) {
    var c = "s._c='s_c';s.wd=window;if(!s.wd.s_c_in){s.wd.s_c_il=new Array;s.wd.s_c_in=0;}s._il=s.wd.s_c_il;s._in=s.wd.s_c_in;s._il[s._in]=s;s.wd.s_c_in++;s"
+ ".an=s_an;s.cls=function(x,c){var i,y='';if(!c)c=this.an;for(i=0;i<x.length;i++){n=x.substring(i,i+1);if(c.indexOf(n)>=0)y+=n}return y};s.fl=function(x,l){return x?(''+x).substring(0,l):x};s.co=func"
+ "tion(o){if(!o)return o;var n=new Object,x;for(x in o)if(x.indexOf('select')<0&&x.indexOf('filter')<0)n[x]=o[x];return n};s.num=function(x){x=''+x;for(var p=0;p<x.length;p++)if(('0123456789').indexO"
+ "f(x.substring(p,p+1))<0)return 0;return 1};s.rep=s_rep;s.sp=s_sp;s.jn=s_jn;s.ape=function(x){var s=this,h='0123456789ABCDEF',i,c=s.charSet,n,l,e,y='';c=c?c.toUpperCase():'';if(x){x=''+x;if(s.em==3)"
+ "return encodeURIComponent(x);else if(c=='AUTO'&&('').charCodeAt){for(i=0;i<x.length;i++){c=x.substring(i,i+1);n=x.charCodeAt(i);if(n>127){l=0;e='';while(n||l<4){e=h.substring(n%16,n%16+1)+e;n=(n-n%"
+ "16)/16;l++}y+='%u'+e}else if(c=='+')y+='%2B';else y+=escape(c)}return y}else{x=s.rep(escape(''+x),'+','%2B');if(c&&s.em==1&&x.indexOf('%u')<0&&x.indexOf('%U')<0){i=x.indexOf('%');while(i>=0){i++;if"
+ "(h.substring(8).indexOf(x.substring(i,i+1).toUpperCase())>=0)return x.substring(0,i)+'u00'+x.substring(i);i=x.indexOf('%',i)}}}}return x};s.epa=function(x){var s=this;if(x){x=''+x;return s.em==3?de"
+ "codeURIComponent(x):unescape(s.rep(x,'+',' '))}return x};s.pt=function(x,d,f,a){var s=this,t=x,z=0,y,r;while(t){y=t.indexOf(d);y=y<0?t.length:y;t=t.substring(0,y);r=s[f](t,a);if(r)return r;z+=y+d.l"
+ "ength;t=x.substring(z,x.length);t=z<x.length?t:''}return ''};s.isf=function(t,a){var c=a.indexOf(':');if(c>=0)a=a.substring(0,c);if(t.substring(0,2)=='s_')t=t.substring(2);return (t!=''&&t==a)};s.f"
+ "sf=function(t,a){var s=this;if(s.pt(a,',','isf',t))s.fsg+=(s.fsg!=''?',':'')+t;return 0};s.fs=function(x,f){var s=this;s.fsg='';s.pt(x,',','fsf',f);return s.fsg};s.si=function(){var s=this,i,k,v,c="
+ "s_gi+'var s=s_gi(\"'+s.oun+'\");s.sa(\"'+s.un+'\");';for(i=0;i<s.va_g.length;i++){k=s.va_g[i];v=s[k];if(v!=undefined){if(typeof(v)=='string')c+='s.'+k+'=\"'+s_fe(v)+'\";';else c+='s.'+k+'='+v+';'}}"
+ "c+=\"s.lnk=s.eo=s.linkName=s.linkType=s.wd.s_objectID=s.ppu=s.pe=s.pev1=s.pev2=s.pev3='';\";return c};s.c_d='';s.c_gdf=function(t,a){var s=this;if(!s.num(t))return 1;return 0};s.c_gd=function(){var"
+ " s=this,d=s.wd.location.hostname,n=s.fpCookieDomainPeriods,p;if(!n)n=s.cookieDomainPeriods;if(d&&!s.c_d){n=n?parseInt(n):2;n=n>2?n:2;p=d.lastIndexOf('.');if(p>=0){while(p>=0&&n>1){p=d.lastIndexOf('"
+ ".',p-1);n--}s.c_d=p>0&&s.pt(d,'.','c_gdf',0)?d.substring(p):d}}return s.c_d};s.c_r=function(k){var s=this;k=s.ape(k);var c=' '+s.d.cookie,i=c.indexOf(' '+k+'='),e=i<0?i:c.indexOf(';',i),v=i<0?'':s."
+ "epa(c.substring(i+2+k.length,e<0?c.length:e));return v!='[[B]]'?v:''};s.c_w=function(k,v,e){var s=this,d=s.c_gd(),l=s.cookieLifetime,t;v=''+v;l=l?(''+l).toUpperCase():'';if(e&&l!='SESSION'&&l!='NON"
+ "E'){t=(v!=''?parseInt(l?l:0):-60);if(t){e=new Date;e.setTime(e.getTime()+(t*1000))}}if(k&&l!='NONE'){s.d.cookie=k+'='+s.ape(v!=''?v:'[[B]]')+'; path=/;'+(e&&l!='SESSION'?' expires='+e.toGMTString()"
+ "+';':'')+(d?' domain='+d+';':'');return s.c_r(k)==v}return 0};s.eh=function(o,e,r,f){var s=this,b='s_'+e+'_'+s._in,n=-1,l,i,x;if(!s.ehl)s.ehl=new Array;l=s.ehl;for(i=0;i<l.length&&n<0;i++){if(l[i]."
+ "o==o&&l[i].e==e)n=i}if(n<0){n=i;l[n]=new Object}x=l[n];x.o=o;x.e=e;f=r?x.b:f;if(r||f){x.b=r?0:o[e];x.o[e]=f}if(x.b){x.o[b]=x.b;return b}return 0};s.cet=function(f,a,t,o,b){var s=this,r,tcf;if(s.apv"
+ ">=5&&(!s.isopera||s.apv>=7)){tcf=new Function('s','f','a','t','var e,r;try{r=s[f](a)}catch(e){r=s[t](e)}return r');r=tcf(s,f,a,t)}else{if(s.ismac&&s.u.indexOf('MSIE 4')>=0)r=s[b](a);else{s.eh(s.wd,"
+ "'onerror',0,o);r=s[f](a);s.eh(s.wd,'onerror',1)}}return r};s.gtfset=function(e){var s=this;return s.tfs};s.gtfsoe=new Function('e','var s=s_c_il['+s._in+'],c;s.eh(window,\"onerror\",1);s.etfs=1;c=s"
+ ".t();if(c)s.d.write(c);s.etfs=0;return true');s.gtfsfb=function(a){return window};s.gtfsf=function(w){var s=this,p=w.parent,l=w.location;s.tfs=w;if(p&&p.location!=l&&p.location.host==l.host){s.tfs="
+ "p;return s.gtfsf(s.tfs)}return s.tfs};s.gtfs=function(){var s=this;if(!s.tfs){s.tfs=s.wd;if(!s.etfs)s.tfs=s.cet('gtfsf',s.tfs,'gtfset',s.gtfsoe,'gtfsfb')}return s.tfs};s.mrq=function(u){var s=this,"
+ "l=s.rl[u],n,r;s.rl[u]=0;if(l)for(n=0;n<l.length;n++){r=l[n];s.mr(0,0,r.r,0,r.t,r.u)}};s.br=function(id,rs){var s=this;if(s.disableBufferedRequests||!s.c_w('s_br',rs))s.brl=rs};s.flushBufferedReques"
+ "ts=function(){this.fbr(0)};s.fbr=function(id){var s=this,br=s.c_r('s_br');if(!br)br=s.brl;if(br){if(!s.disableBufferedRequests)s.c_w('s_br','');s.mr(0,0,br)}s.brl=0};s.mr=function(sess,q,rs,id,ta,u"
+ "){var s=this,dc=s.dc,t1=s.trackingServer,t2=s.trackingServerSecure,tb=s.trackingServerBase,p='.sc',ns=s.visitorNamespace,un=s.cls(u?u:(ns?ns:s.fun)),r=new Object,l,imn='s_i_'+(un),im,b,e;if(!rs){if"
+ "(t1){if(t2&&s.ssl)t1=t2}else{if(!tb)tb='2o7.net';if(dc)dc=(''+dc).toLowerCase();else dc='d1';if(tb=='2o7.net'){if(dc=='d1')dc='112';else if(dc=='d2')dc='122';p=''}t1=un+'.'+dc+'.'+p+tb}rs='http'+(s"
+ ".ssl?'s':'')+'://'+t1+'/b/ss/'+s.un+'/'+(s.mobile?'5.1':'1')+'/H.22.1/'+sess+'?AQB=1&ndh=1'+(q?q:'')+'&AQE=1';if(s.isie&&!s.ismac)rs=s.fl(rs,2047);if(id){s.br(id,rs);return}}if(s.d.images&&s.apv>=3"
+ "&&(!s.isopera||s.apv>=7)&&(s.ns6<0||s.apv>=6.1)){if(!s.rc)s.rc=new Object;if(!s.rc[un]){s.rc[un]=1;if(!s.rl)s.rl=new Object;s.rl[un]=new Array;setTimeout('if(window.s_c_il)window.s_c_il['+s._in+']."
+ "mrq(\"'+un+'\")',750)}else{l=s.rl[un];if(l){r.t=ta;r.u=un;r.r=rs;l[l.length]=r;return ''}imn+='_'+s.rc[un];s.rc[un]++}im=s.wd[imn];if(!im)im=s.wd[imn]=new Image;im.s_l=0;im.onload=new Function('e',"
+ "'this.s_l=1;var wd=window,s;if(wd.s_c_il){s=wd.s_c_il['+s._in+'];s.mrq(\"'+un+'\");s.nrs--;if(!s.nrs)s.m_m(\"rr\")}');if(!s.nrs){s.nrs=1;s.m_m('rs')}else s.nrs++;im.src=rs;if((!ta||ta=='_self'||ta="
+ "='_top'||(s.wd.name&&ta==s.wd.name))&&rs.indexOf('&pe=')>=0){b=e=new Date;while(!im.s_l&&e.getTime()-b.getTime()<500)e=new Date}return ''}return '<im'+'g sr'+'c=\"'+rs+'\" width=1 height=1 border=0"
+ " alt=\"\">'};s.gg=function(v){var s=this;if(!s.wd['s_'+v])s.wd['s_'+v]='';return s.wd['s_'+v]};s.glf=function(t,a){if(t.substring(0,2)=='s_')t=t.substring(2);var s=this,v=s.gg(t);if(v)s[t]=v};s.gl="
+ "function(v){var s=this;if(s.pg)s.pt(v,',','glf',0)};s.rf=function(x){var s=this,y,i,j,h,l,a,b='',c='',t;if(x){y=''+x;i=y.indexOf('?');if(i>0){a=y.substring(i+1);y=y.substring(0,i);h=y.toLowerCase()"
+ ";i=0;if(h.substring(0,7)=='http://')i+=7;else if(h.substring(0,8)=='https://')i+=8;h=h.substring(i);i=h.indexOf(\"/\");if(i>0){h=h.substring(0,i);if(h.indexOf('google')>=0){a=s.sp(a,'&');if(a.lengt"
+ "h>1){l=',q,ie,start,search_key,word,kw,cd,';for(j=0;j<a.length;j++){t=a[j];i=t.indexOf('=');if(i>0&&l.indexOf(','+t.substring(0,i)+',')>=0)b+=(b?'&':'')+t;else c+=(c?'&':'')+t}if(b&&c){y+='?'+b+'&'"
+ "+c;if(''+x!=y)x=y}}}}}}return x};s.hav=function(){var s=this,qs='',fv=s.linkTrackVars,fe=s.linkTrackEvents,mn,i;if(s.pe){mn=s.pe.substring(0,1).toUpperCase()+s.pe.substring(1);if(s[mn]){fv=s[mn].tr"
+ "ackVars;fe=s[mn].trackEvents}}fv=fv?fv+','+s.vl_l+','+s.vl_l2:'';for(i=0;i<s.va_t.length;i++){var k=s.va_t[i],v=s[k],b=k.substring(0,4),x=k.substring(4),n=parseInt(x),q=k;if(v&&k!='linkName'&&k!='l"
+ "inkType'){if(s.pe||s.lnk||s.eo){if(fv&&(','+fv+',').indexOf(','+k+',')<0)v='';if(k=='events'&&fe)v=s.fs(v,fe)}if(v){if(k=='dynamicVariablePrefix')q='D';else if(k=='visitorID')q='vid';else if(k=='pa"
+ "geURL'){q='g';v=s.fl(v,255)}else if(k=='referrer'){q='r';v=s.fl(s.rf(v),255)}else if(k=='vmk'||k=='visitorMigrationKey')q='vmt';else if(k=='visitorMigrationServer'){q='vmf';if(s.ssl&&s.visitorMigra"
+ "tionServerSecure)v=''}else if(k=='visitorMigrationServerSecure'){q='vmf';if(!s.ssl&&s.visitorMigrationServer)v=''}else if(k=='charSet'){q='ce';if(v.toUpperCase()=='AUTO')v='ISO8859-1';else if(s.em="
+ "=2||s.em==3)v='UTF-8'}else if(k=='visitorNamespace')q='ns';else if(k=='cookieDomainPeriods')q='cdp';else if(k=='cookieLifetime')q='cl';else if(k=='variableProvider')q='vvp';else if(k=='currencyCode"
+ "')q='cc';else if(k=='channel')q='ch';else if(k=='transactionID')q='xact';else if(k=='campaign')q='v0';else if(k=='resolution')q='s';else if(k=='colorDepth')q='c';else if(k=='javascriptVersion')q='j"
+ "';else if(k=='javaEnabled')q='v';else if(k=='cookiesEnabled')q='k';else if(k=='browserWidth')q='bw';else if(k=='browserHeight')q='bh';else if(k=='connectionType')q='ct';else if(k=='homepage')q='hp'"
+ ";else if(k=='plugins')q='p';else if(s.num(x)){if(b=='prop')q='c'+n;else if(b=='eVar')q='v'+n;else if(b=='list')q='l'+n;else if(b=='hier'){q='h'+n;v=s.fl(v,255)}}if(v)qs+='&'+q+'='+(k.substring(0,3)"
+ "!='pev'?s.ape(v):v)}}}return qs};s.ltdf=function(t,h){t=t?t.toLowerCase():'';h=h?h.toLowerCase():'';var qi=h.indexOf('?');h=qi>=0?h.substring(0,qi):h;if(t&&h.substring(h.length-(t.length+1))=='.'+t"
+ ")return 1;return 0};s.ltef=function(t,h){t=t?t.toLowerCase():'';h=h?h.toLowerCase():'';if(t&&h.indexOf(t)>=0)return 1;return 0};s.lt=function(h){var s=this,lft=s.linkDownloadFileTypes,lef=s.linkExt"
+ "ernalFilters,lif=s.linkInternalFilters;lif=lif?lif:s.wd.location.hostname;h=h.toLowerCase();if(s.trackDownloadLinks&&lft&&s.pt(lft,',','ltdf',h))return 'd';if(s.trackExternalLinks&&h.substring(0,1)"
+ "!='#'&&(lef||lif)&&(!lef||s.pt(lef,',','ltef',h))&&(!lif||!s.pt(lif,',','ltef',h)))return 'e';return ''};s.lc=new Function('e','var s=s_c_il['+s._in+'],b=s.eh(this,\"onclick\");s.lnk=s.co(this);s.t"
+ "();s.lnk=0;if(b)return this[b](e);return true');s.bc=new Function('e','var s=s_c_il['+s._in+'],f,tcf;if(s.d&&s.d.all&&s.d.all.cppXYctnr)return;s.eo=e.srcElement?e.srcElement:e.target;tcf=new Functi"
+ "on(\"s\",\"var e;try{if(s.eo&&(s.eo.tagName||s.eo.parentElement||s.eo.parentNode))s.t()}catch(e){}\");tcf(s);s.eo=0');s.oh=function(o){var s=this,l=s.wd.location,h=o.href?o.href:'',i,j,k,p;i=h.inde"
+ "xOf(':');j=h.indexOf('?');k=h.indexOf('/');if(h&&(i<0||(j>=0&&i>j)||(k>=0&&i>k))){p=o.protocol&&o.protocol.length>1?o.protocol:(l.protocol?l.protocol:'');i=l.pathname.lastIndexOf('/');h=(p?p+'//':'"
+ "')+(o.host?o.host:(l.host?l.host:''))+(h.substring(0,1)!='/'?l.pathname.substring(0,i<0?0:i)+'/':'')+h}return h};s.ot=function(o){var t=o.tagName;t=t&&t.toUpperCase?t.toUpperCase():'';if(t=='SHAPE'"
+ ")t='';if(t){if((t=='INPUT'||t=='BUTTON')&&o.type&&o.type.toUpperCase)t=o.type.toUpperCase();else if(!t&&o.href)t='A';}return t};s.oid=function(o){var s=this,t=s.ot(o),p,c,n='',x=0;if(t&&!o.s_oid){p"
+ "=o.protocol;c=o.onclick;if(o.href&&(t=='A'||t=='AREA')&&(!c||!p||p.toLowerCase().indexOf('javascript')<0))n=s.oh(o);else if(c){n=s.rep(s.rep(s.rep(s.rep(''+c,\"\\r\",''),\"\\n\",''),\"\\t\",''),' '"
+ ",'');x=2}else if(t=='INPUT'||t=='SUBMIT'){if(o.value)n=o.value;else if(o.innerText)n=o.innerText;else if(o.textContent)n=o.textContent;x=3}else if(o.src&&t=='IMAGE')n=o.src;if(n){o.s_oid=s.fl(n,100"
+ ");o.s_oidt=x}}return o.s_oid};s.rqf=function(t,un){var s=this,e=t.indexOf('='),u=e>=0?t.substring(0,e):'',q=e>=0?s.epa(t.substring(e+1)):'';if(u&&q&&(','+u+',').indexOf(','+un+',')>=0){if(u!=s.un&&"
+ "s.un.indexOf(',')>=0)q='&u='+u+q+'&u=0';return q}return ''};s.rq=function(un){if(!un)un=this.un;var s=this,c=un.indexOf(','),v=s.c_r('s_sq'),q='';if(c<0)return s.pt(v,'&','rqf',un);return s.pt(un,'"
+ ",','rq',0)};s.sqp=function(t,a){var s=this,e=t.indexOf('='),q=e<0?'':s.epa(t.substring(e+1));s.sqq[q]='';if(e>=0)s.pt(t.substring(0,e),',','sqs',q);return 0};s.sqs=function(un,q){var s=this;s.squ[u"
+ "n]=q;return 0};s.sq=function(q){var s=this,k='s_sq',v=s.c_r(k),x,c=0;s.sqq=new Object;s.squ=new Object;s.sqq[q]='';s.pt(v,'&','sqp',0);s.pt(s.un,',','sqs',q);v='';for(x in s.squ)if(x&&(!Object||!Ob"
+ "ject.prototype||!Object.prototype[x]))s.sqq[s.squ[x]]+=(s.sqq[s.squ[x]]?',':'')+x;for(x in s.sqq)if(x&&(!Object||!Object.prototype||!Object.prototype[x])&&s.sqq[x]&&(x==q||c<2)){v+=(v?'&':'')+s.sqq"
+ "[x]+'='+s.ape(x);c++}return s.c_w(k,v,0)};s.wdl=new Function('e','var s=s_c_il['+s._in+'],r=true,b=s.eh(s.wd,\"onload\"),i,o,oc;if(b)r=this[b](e);for(i=0;i<s.d.links.length;i++){o=s.d.links[i];oc=o"
+ ".onclick?\"\"+o.onclick:\"\";if((oc.indexOf(\"s_gs(\")<0||oc.indexOf(\".s_oc(\")>=0)&&oc.indexOf(\".tl(\")<0)s.eh(o,\"onclick\",0,s.lc);}return r');s.wds=function(){var s=this;if(s.apv>3&&(!s.isie|"
+ "|!s.ismac||s.apv>=5)){if(s.b&&s.b.attachEvent)s.b.attachEvent('onclick',s.bc);else if(s.b&&s.b.addEventListener)s.b.addEventListener('click',s.bc,false);else s.eh(s.wd,'onload',0,s.wdl)}};s.vs=func"
+ "tion(x){var s=this,v=s.visitorSampling,g=s.visitorSamplingGroup,k='s_vsn_'+s.un+(g?'_'+g:''),n=s.c_r(k),e=new Date,y=e.getYear();e.setYear(y+10+(y<1900?1900:0));if(v){v*=100;if(!n){if(!s.c_w(k,x,e)"
+ ")return 0;n=x}if(n%10000>v)return 0}return 1};s.dyasmf=function(t,m){if(t&&m&&m.indexOf(t)>=0)return 1;return 0};s.dyasf=function(t,m){var s=this,i=t?t.indexOf('='):-1,n,x;if(i>=0&&m){var n=t.subst"
+ "ring(0,i),x=t.substring(i+1);if(s.pt(x,',','dyasmf',m))return n}return 0};s.uns=function(){var s=this,x=s.dynamicAccountSelection,l=s.dynamicAccountList,m=s.dynamicAccountMatch,n,i;s.un=s.un.toLowe"
+ "rCase();if(x&&l){if(!m)m=s.wd.location.host;if(!m.toLowerCase)m=''+m;l=l.toLowerCase();m=m.toLowerCase();n=s.pt(l,';','dyasf',m);if(n)s.un=n}i=s.un.indexOf(',');s.fun=i<0?s.un:s.un.substring(0,i)};"
+ "s.sa=function(un){var s=this;s.un=un;if(!s.oun)s.oun=un;else if((','+s.oun+',').indexOf(','+un+',')<0)s.oun+=','+un;s.uns()};s.m_i=function(n,a){var s=this,m,f=n.substring(0,1),r,l,i;if(!s.m_l)s.m_"
+ "l=new Object;if(!s.m_nl)s.m_nl=new Array;m=s.m_l[n];if(!a&&m&&m._e&&!m._i)s.m_a(n);if(!m){m=new Object,m._c='s_m';m._in=s.wd.s_c_in;m._il=s._il;m._il[m._in]=m;s.wd.s_c_in++;m.s=s;m._n=n;m._l=new Ar"
+ "ray('_c','_in','_il','_i','_e','_d','_dl','s','n','_r','_g','_g1','_t','_t1','_x','_x1','_rs','_rr','_l');s.m_l[n]=m;s.m_nl[s.m_nl.length]=n}else if(m._r&&!m._m){r=m._r;r._m=m;l=m._l;for(i=0;i<l.le"
+ "ngth;i++)if(m[l[i]])r[l[i]]=m[l[i]];r._il[r._in]=r;m=s.m_l[n]=r}if(f==f.toUpperCase())s[n]=m;return m};s.m_a=new Function('n','g','e','if(!g)g=\"m_\"+n;var s=s_c_il['+s._in+'],c=s[g+\"_c\"],m,x,f=0"
+ ";if(!c)c=s.wd[\"s_\"+g+\"_c\"];if(c&&s_d)s[g]=new Function(\"s\",s_ft(s_d(c)));x=s[g];if(!x)x=s.wd[\\'s_\\'+g];if(!x)x=s.wd[g];m=s.m_i(n,1);if(x&&(!m._i||g!=\"m_\"+n)){m._i=f=1;if((\"\"+x).indexOf("
+ "\"function\")>=0)x(s);else s.m_m(\"x\",n,x,e)}m=s.m_i(n,1);if(m._dl)m._dl=m._d=0;s.dlt();return f');s.m_m=function(t,n,d,e){t='_'+t;var s=this,i,x,m,f='_'+t,r=0,u;if(s.m_l&&s.m_nl)for(i=0;i<s.m_nl."
+ "length;i++){x=s.m_nl[i];if(!n||x==n){m=s.m_i(x);u=m[t];if(u){if((''+u).indexOf('function')>=0){if(d&&e)u=m[t](d,e);else if(d)u=m[t](d);else u=m[t]()}}if(u)r=1;u=m[t+1];if(u&&!m[f]){if((''+u).indexO"
+ "f('function')>=0){if(d&&e)u=m[t+1](d,e);else if(d)u=m[t+1](d);else u=m[t+1]()}}m[f]=1;if(u)r=1}}return r};s.m_ll=function(){var s=this,g=s.m_dl,i,o;if(g)for(i=0;i<g.length;i++){o=g[i];if(o)s.loadMo"
+ "dule(o.n,o.u,o.d,o.l,o.e,1);g[i]=0}};s.loadModule=function(n,u,d,l,e,ln){var s=this,m=0,i,g,o=0,f1,f2,c=s.h?s.h:s.b,b,tcf;if(n){i=n.indexOf(':');if(i>=0){g=n.substring(i+1);n=n.substring(0,i)}else "
+ "g=\"m_\"+n;m=s.m_i(n)}if((l||(n&&!s.m_a(n,g)))&&u&&s.d&&c&&s.d.createElement){if(d){m._d=1;m._dl=1}if(ln){if(s.ssl)u=s.rep(u,'http:','https:');i='s_s:'+s._in+':'+n+':'+g;b='var s=s_c_il['+s._in+'],"
+ "o=s.d.getElementById(\"'+i+'\");if(s&&o){if(!o.l&&s.wd.'+g+'){o.l=1;if(o.i)clearTimeout(o.i);o.i=0;s.m_a(\"'+n+'\",\"'+g+'\"'+(e?',\"'+e+'\"':'')+')}';f2=b+'o.c++;if(!s.maxDelay)s.maxDelay=250;if(!"
+ "o.l&&o.c<(s.maxDelay*2)/100)o.i=setTimeout(o.f2,100)}';f1=new Function('e',b+'}');tcf=new Function('s','c','i','u','f1','f2','var e,o=0;try{o=s.d.createElement(\"script\");if(o){o.type=\"text/javas"
+ "cript\";'+(n?'o.id=i;o.defer=true;o.onload=o.onreadystatechange=f1;o.f2=f2;o.l=0;':'')+'o.src=u;c.appendChild(o);'+(n?'o.c=0;o.i=setTimeout(f2,100)':'')+'}}catch(e){o=0}return o');o=tcf(s,c,i,u,f1,"
+ "f2)}else{o=new Object;o.n=n+':'+g;o.u=u;o.d=d;o.l=l;o.e=e;g=s.m_dl;if(!g)g=s.m_dl=new Array;i=0;while(i<g.length&&g[i])i++;g[i]=o}}else if(n){m=s.m_i(n);m._e=1}return m};s.vo1=function(t,a){if(a[t]"
+ "||a['!'+t])this[t]=a[t]};s.vo2=function(t,a){if(!a[t]){a[t]=this[t];if(!a[t])a['!'+t]=1}};s.dlt=new Function('var s=s_c_il['+s._in+'],d=new Date,i,vo,f=0;if(s.dll)for(i=0;i<s.dll.length;i++){vo=s.d"
+ "ll[i];if(vo){if(!s.m_m(\"d\")||d.getTime()-vo._t>=s.maxDelay){s.dll[i]=0;s.t(vo)}else f=1}}if(s.dli)clearTimeout(s.dli);s.dli=0;if(f){if(!s.dli)s.dli=setTimeout(s.dlt,s.maxDelay)}else s.dll=0');s.d"
+ "l=function(vo){var s=this,d=new Date;if(!vo)vo=new Object;s.pt(s.vl_g,',','vo2',vo);vo._t=d.getTime();if(!s.dll)s.dll=new Array;s.dll[s.dll.length]=vo;if(!s.maxDelay)s.maxDelay=250;s.dlt()};s.t=fun"
+ "ction(vo,id){var s=this,trk=1,tm=new Date,sed=Math&&Math.random?Math.floor(Math.random()*10000000000000):tm.getTime(),sess='s'+Math.floor(tm.getTime()/10800000)%10+sed,y=tm.getYear(),vt=tm.getDate("
+ ")+'/'+tm.getMonth()+'/'+(y<1900?y+1900:y)+' '+tm.getHours()+':'+tm.getMinutes()+':'+tm.getSeconds()+' '+tm.getDay()+' '+tm.getTimezoneOffset(),tcf,tfs=s.gtfs(),ta=-1,q='',qs='',code='',vb=new Objec"
+ "t;s.gl(s.vl_g);s.uns();s.m_ll();if(!s.td){var tl=tfs.location,a,o,i,x='',c='',v='',p='',bw='',bh='',j='1.0',k=s.c_w('s_cc','true',0)?'Y':'N',hp='',ct='',pn=0,ps;if(String&&String.prototype){j='1.1'"
+ ";if(j.match){j='1.2';if(tm.setUTCDate){j='1.3';if(s.isie&&s.ismac&&s.apv>=5)j='1.4';if(pn.toPrecision){j='1.5';a=new Array;if(a.forEach){j='1.6';i=0;o=new Object;tcf=new Function('o','var e,i=0;try"
+ "{i=new Iterator(o)}catch(e){}return i');i=tcf(o);if(i&&i.next)j='1.7'}}}}}if(s.apv>=4)x=screen.width+'x'+screen.height;if(s.isns||s.isopera){if(s.apv>=3){v=s.n.javaEnabled()?'Y':'N';if(s.apv>=4){c="
+ "screen.pixelDepth;bw=s.wd.innerWidth;bh=s.wd.innerHeight}}s.pl=s.n.plugins}else if(s.isie){if(s.apv>=4){v=s.n.javaEnabled()?'Y':'N';c=screen.colorDepth;if(s.apv>=5){bw=s.d.documentElement.offsetWid"
+ "th;bh=s.d.documentElement.offsetHeight;if(!s.ismac&&s.b){tcf=new Function('s','tl','var e,hp=0;try{s.b.addBehavior(\"#default#homePage\");hp=s.b.isHomePage(tl)?\"Y\":\"N\"}catch(e){}return hp');hp="
+ "tcf(s,tl);tcf=new Function('s','var e,ct=0;try{s.b.addBehavior(\"#default#clientCaps\");ct=s.b.connectionType}catch(e){}return ct');ct=tcf(s)}}}else r=''}if(s.pl)while(pn<s.pl.length&&pn<30){ps=s.f"
+ "l(s.pl[pn].name,100)+';';if(p.indexOf(ps)<0)p+=ps;pn++}s.resolution=x;s.colorDepth=c;s.javascriptVersion=j;s.javaEnabled=v;s.cookiesEnabled=k;s.browserWidth=bw;s.browserHeight=bh;s.connectionType=c"
+ "t;s.homepage=hp;s.plugins=p;s.td=1}if(vo){s.pt(s.vl_g,',','vo2',vb);s.pt(s.vl_g,',','vo1',vo)}if((vo&&vo._t)||!s.m_m('d')){if(s.usePlugins)s.doPlugins(s);var l=s.wd.location,r=tfs.document.referrer"
+ ";if(!s.pageURL)s.pageURL=l.href?l.href:l;if(!s.referrer&&!s._1_referrer){s.referrer=r;s._1_referrer=1}s.m_m('g');if(s.lnk||s.eo){var o=s.eo?s.eo:s.lnk;if(!o)return '';var p=s.pageName,w=1,t=s.ot(o)"
+ ",n=s.oid(o),x=o.s_oidt,h,l,i,oc;if(s.eo&&o==s.eo){while(o&&!n&&t!='BODY'){o=o.parentElement?o.parentElement:o.parentNode;if(!o)return '';t=s.ot(o);n=s.oid(o);x=o.s_oidt}oc=o.onclick?''+o.onclick:''"
+ ";if((oc.indexOf(\"s_gs(\")>=0&&oc.indexOf(\".s_oc(\")<0)||oc.indexOf(\".tl(\")>=0)return ''}if(n)ta=o.target;h=s.oh(o);i=h.indexOf('?');h=s.linkLeaveQueryString||i<0?h:h.substring(0,i);l=s.linkName"
+ ";t=s.linkType?s.linkType.toLowerCase():s.lt(h);if(t&&(h||l))q+='&pe=lnk_'+(t=='d'||t=='e'?s.ape(t):'o')+(h?'&pev1='+s.ape(h):'')+(l?'&pev2='+s.ape(l):'');else trk=0;if(s.trackInlineStats){if(!p){p="
+ "s.pageURL;w=0}t=s.ot(o);i=o.sourceIndex;if(s.gg('objectID')){n=s.gg('objectID');x=1;i=1}if(p&&n&&t)qs='&pid='+s.ape(s.fl(p,255))+(w?'&pidt='+w:'')+'&oid='+s.ape(s.fl(n,100))+(x?'&oidt='+x:'')+'&ot="
+ "'+s.ape(t)+(i?'&oi='+i:'')}}if(!trk&&!qs)return '';s.sampled=s.vs(sed);if(trk){if(s.sampled)code=s.mr(sess,(vt?'&t='+s.ape(vt):'')+s.hav()+q+(qs?qs:s.rq()),0,id,ta);qs='';s.m_m('t');if(s.p_r)s.p_r("
+ ");s.referrer=''}s.sq(qs);}else{s.dl(vo);}if(vo)s.pt(s.vl_g,',','vo1',vb);s.lnk=s.eo=s.linkName=s.linkType=s.wd.s_objectID=s.ppu=s.pe=s.pev1=s.pev2=s.pev3='';if(s.pg)s.wd.s_lnk=s.wd.s_eo=s.wd.s_link"
+ "Name=s.wd.s_linkType='';if(!id&&!s.tc){s.tc=1;s.flushBufferedRequests()}return code};s.tl=function(o,t,n,vo){var s=this;s.lnk=s.co(o);s.linkType=t;s.linkName=n;s.t(vo)};if(pg){s.wd.s_co=function(o)"
+ "{var s=s_gi(\"_\",1,1);return s.co(o)};s.wd.s_gs=function(un){var s=s_gi(un,1,1);return s.t()};s.wd.s_dc=function(un){var s=s_gi(un,1);return s.t()}}s.ssl=(s.wd.location.protocol.toLowerCase().inde"
+ "xOf('https')>=0);s.d=document;s.b=s.d.body;if(s.d.getElementsByTagName){s.h=s.d.getElementsByTagName('HEAD');if(s.h)s.h=s.h[0]}s.n=navigator;s.u=s.n.userAgent;s.ns6=s.u.indexOf('Netscape6/');var ap"
+ "n=s.n.appName,v=s.n.appVersion,ie=v.indexOf('MSIE '),o=s.u.indexOf('Opera '),i;if(v.indexOf('Opera')>=0||o>0)apn='Opera';s.isie=(apn=='Microsoft Internet Explorer');s.isns=(apn=='Netscape');s.isope"
+ "ra=(apn=='Opera');s.ismac=(s.u.indexOf('Mac')>=0);if(o>0)s.apv=parseFloat(s.u.substring(o+6));else if(ie>0){s.apv=parseInt(i=v.substring(ie+5));if(s.apv>3)s.apv=parseFloat(i)}else if(s.ns6>0)s.apv="
+ "parseFloat(s.u.substring(s.ns6+10));else s.apv=parseFloat(v);s.em=0;if(s.em.toPrecision)s.em=3;else if(String.fromCharCode){i=escape(String.fromCharCode(256)).toUpperCase();s.em=(i=='%C4%80'?2:(i=="
+ "'%U0100'?1:0))}s.sa(un);s.vl_l='dynamicVariablePrefix,visitorID,vmk,visitorMigrationKey,visitorMigrationServer,visitorMigrationServerSecure,ppu,charSet,visitorNamespace,cookieDomainPeriods,cookieLi"
+ "fetime,pageName,pageURL,referrer,currencyCode';s.va_l=s.sp(s.vl_l,',');s.vl_t=s.vl_l+',variableProvider,channel,server,pageType,transactionID,purchaseID,campaign,state,zip,events,products,linkName,"
+ "linkType';for(var n=1;n<76;n++)s.vl_t+=',prop'+n+',eVar'+n+',hier'+n+',list'+n;s.vl_l2=',tnt,pe,pev1,pev2,pev3,resolution,colorDepth,javascriptVersion,javaEnabled,cookiesEnabled,browserWidth,browse"
+ "rHeight,connectionType,homepage,plugins';s.vl_t+=s.vl_l2;s.va_t=s.sp(s.vl_t,',');s.vl_g=s.vl_t+',trackingServer,trackingServerSecure,trackingServerBase,fpCookieDomainPeriods,disableBufferedRequests"
+ ",mobile,visitorSampling,visitorSamplingGroup,dynamicAccountSelection,dynamicAccountList,dynamicAccountMatch,trackDownloadLinks,trackExternalLinks,trackInlineStats,linkLeaveQueryString,linkDownloadF"
+ "ileTypes,linkExternalFilters,linkInternalFilters,linkTrackVars,linkTrackEvents,linkNames,lnk,eo,_1_referrer';s.va_g=s.sp(s.vl_g,',');s.pg=pg;s.gl(s.vl_g);if(!ss)s.wds()",
w = window, l = w.s_c_il, n = navigator, u = n.userAgent, v = n.appVersion, e = v.indexOf('MSIE '), m = u.indexOf('Netscape6/'), a, i, s; if (un) { un = un.toLowerCase(); if (l) for (i = 0; i < l.length; i++) { s = l[i]; if (!s._c || s._c == 's_c') { if (s.oun == un) return s; else if (s.fs && s.sa && s.fs(s.oun, un)) { s.sa(un); return s } } } } w.s_an = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    w.s_sp = new Function("x", "d", "var a=new Array,i=0,j;if(x){if(x.split)a=x.split(d);else if(!d)for(i=0;i<x.length;i++)a[a.length]=x.substring(i,i+1);else while(i>=0){j=x.indexOf(d,i);a[a.length]=x.subst"
+ "ring(i,j<0?x.length:j);i=j;if(i>=0)i+=d.length}}return a");
    w.s_jn = new Function("a", "d", "var x='',i,j=a.length;if(a&&j>0){x=a[0];if(j>1){if(a.join)x=a.join(d);else for(i=1;i<j;i++)x+=d+a[i]}}return x");
    w.s_rep = new Function("x", "o", "n", "return s_jn(s_sp(x,o),n)");
    w.s_d = new Function("x", "var t='`^@$#',l=s_an,l2=new Object,x2,d,b=0,k,i=x.lastIndexOf('~~'),j,v,w;if(i>0){d=x.substring(0,i);x=x.substring(i+2);l=s_sp(l,'');for(i=0;i<62;i++)l2[l[i]]=i;t=s_sp(t,'');d"
+ "=s_sp(d,'~');i=0;while(i<5){v=0;if(x.indexOf(t[i])>=0) {x2=s_sp(x,t[i]);for(j=1;j<x2.length;j++){k=x2[j].substring(0,1);w=t[i]+k;if(k!=' '){v=1;w=d[b+l2[k]]}x2[j]=w+x2[j].substring(1)}}if(v)x=s_jn("
+ "x2,'');else{w=t[i]+' ';if(x.indexOf(w)>=0)x=s_rep(x,w,t[i]);i++;b+=62}}}return x");
    w.s_fe = new Function("c", "return s_rep(s_rep(s_rep(c,'\\\\','\\\\\\\\'),'\"','\\\\\"'),\"\\n\",\"\\\\n\")");
    w.s_fa = new Function("f", "var s=f.indexOf('(')+1,e=f.indexOf(')'),a='',c;while(s>=0&&s<e){c=f.substring(s,s+1);if(c==',')a+='\",\"';else if((\"\\n\\r\\t \").indexOf(c)<0)a+=c;s++}return a?'\"'+a+'\"':"
+ "a");
    w.s_ft = new Function("c", "c+='';var s,e,o,a,d,q,f,h,x;s=c.indexOf('=function(');while(s>=0){s++;d=1;q='';x=0;f=c.substring(s);a=s_fa(f);e=o=c.indexOf('{',s);e++;while(d>0){h=c.substring(e,e+1);if(q){i"
+ "f(h==q&&!x)q='';if(h=='\\\\')x=x?0:1;else x=0}else{if(h=='\"'||h==\"'\")q=h;if(h=='{')d++;if(h=='}')d--}if(d>0)e++}c=c.substring(0,s)+'new Function('+(a?a+',':'')+'\"'+s_fe(c.substring(o+1,e))+'\")"
+ "'+c.substring(e+1);s=c.indexOf('=function(')}return c;");
    c = s_d(c); if (e > 0) { a = parseInt(i = v.substring(e + 5)); if (a > 3) a = parseFloat(i) } else if (m > 0) a = parseFloat(u.substring(m + 10)); else a = parseFloat(v); if (a >= 5 && v.indexOf('Opera') < 0 && u.indexOf('Opera') < 0) { w.s_c = new Function("un", "pg", "ss", "var s=this;" + c); return new s_c(un, pg, ss) } else s = new Function("un", "pg", "ss", "var s=new Object;" + s_ft(c) + ";return s"); return s(un, pg, ss)
}
;
//Polyfill deprecated jquery functions that have been remove in new versions of jquery but have not yet been restored in jquery migrate plugin

(function ($, undefined) {
    'use strict';
    if (!$.curCSS) {
        $.curCSS = function () {
            console.warn('$.curCSS() is deprecated, please use the standard $.css() instead.'); // eslint-disable-line no-console
            $.css.apply($, arguments);
        };
    }
})(jQuery);
;
jQuery.postJSON = function (url, data, callback, async, errorcallback, addqs) {
    var clearHeaders = function (xhr) { //get rid of unnecessary headers to make request a little lighter
        function safeSet(k, v) {
            try {
                xhr.setRequestHeader(k, v);
            } catch (e) {
                // catch exception
            }
        }
        safeSet('User-Agent', null);
        safeSet('Accept', null);
        safeSet('Accept-Language', null);
        safeSet('Connection', 'keep-alive');
        safeSet('Keep-Alive', null);
    };
    // add data to URL, as sometimes data is lost in POST
    if (addqs || addqs == null) {
        var qs = data == null ? '' : jQuery.param(data);
        url = url.indexOf('?') >= 0 ? jQuery.format('{0}&{1}', url, qs) : jQuery.format('{0}?{1}', url, qs);
    }
    return jQuery.ajax({
        type: 'POST',
        url: url,
        data: data == null ? '' : (addqs || addqs == null) ? '' : data,
        cache: false,
        async: async == null ? true : false,
        success: callback,
        error: errorcallback,
        dataType: 'json',
        beforeSend: function(xml) {
            xml.setRequestHeader('X-IsJson', 'true');
            clearHeaders(xml);
        }
    });
};

;
// PLEASE DO NOT ADD GLOBAL FUNCTIONS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// If you need to add global functions, ask yourself why. Everything should be scoped to a namespace!
// If you still need to add them globally, add them to either KBB.Trident.Web\js\kbb.js or KBB.Trident.Web\js\kbb\KBB.legacy.js
// Not this file!!

$.window = $(window);
$.document = $(document);

var KBB = KBB || {};

//KBB config options, be careful if you modify!
/*eslint-disable no-console */
KBB.config = {
    dev: (!s_account || s_account === 'kbbnextdev' || s_account === 'kbbmobileglobaldev' || s_account === 'kbbmaindevh'),
    enableOmniture: true,
    turnOnDev: function () {
        'use strict';
        window.errorJsLogging = KBB.config.dev = true;
        for (var i = 0, length = console._polyfills.length; i < length; i++) {
            var name = console._polyfills[i];
            if (console['_native' + name]) {
                console[name] = console['_native' + name];
            }
        }
    }
};

(function (console) {
    'use strict';
    //Override console.error() to go through KbbErrorHandler
    console._nativeerror = console.error || console.warn || console.info || console.log || $.noop;
    console.error = function (e) {
        if (e && e != '[ERROR]\t' && window.KbbErrorHandler) {
            KbbErrorHandler.handle.apply(KbbErrorHandler, arguments);
        } else if (KBB.config.dev) {
            var args = Array.prototype.slice.call(arguments);
            if ((e = args[args.length - 1]).stack) {
                args.push('\n' + e.stack);
            }

            if (console._nativeerror.apply) {
                //////PSA: If you got here trying to find where the error you are debugging originated, try using the call stack instead!!!    -Spiderman
                console._nativeerror.apply(console, args);
            }
            else {
                console._nativeerror(Array.prototype.join.call(args, ' '));
            }

            if (!e.stack) {
                console.trace();
            }
        }
    };

    //Polyfill the console if in production or function doesnt exist
    console._polyfills = ['log', 'debug', 'warn', 'info', 'trace'];
    for (var i = 0, length = console._polyfills.length; i < length; i++) {
        var name = console._polyfills[i];
        if (!KBB.config.dev || !console[name]) {
            console['_native' + name] = console[name];
            console[name] = $.noop;
        }
    }
})(window.console = window.console || {});
/*eslint-enable no-console */

//Setting up KBB namespace
$.extend(KBB, (function () {
    var _ads = [];
    return {
        versions: {
            data: window.dataVersionId || 0,
            assembly: window.assemblyVersion || 0
        },
        extend: function (dest, src) {
            for (var prop in src) {
                if (src.hasOwnProperty(prop)) {
                    dest[prop] = src[prop];
                }
            }
            return dest;
        },
        get: function (namespace) {
            var split, ret = KBB;
            if (typeof namespace === 'undefined') {
                return;
            }
            split = (namespace + '').split('.');
            for (var i = 0; i < split.length; i++) {
                if (typeof ret === 'undefined') {
                    return;
                }
                ret = ret[split[i]];
            }
            return ret;
        },
        events: (function () {
            var _callbacks = {},
                contains = function (name) {
                    return typeof _callbacks[name] !== 'undefined';
                };

            return {
                on: function (name, cb) {
                    if (!$.isFunction(cb)) {
                        throw 'An invalid subscriber was added to {0}'.format(name);
                    }
                    if (!contains(name)) {
                        _callbacks[name] = [];
                    }
                    _callbacks[name].push(cb);
                },
                off: function (name) {
                    if (contains(name)) {
                        _callbacks[name] = [];
                    }
                },
                fire: function (name) {
                    for (cb in _callbacks[name]) {
                        var f = _callbacks[name][cb];
                        try {
                            f.apply(this, Array.prototype.slice.call(arguments, 1));
                        } catch (e) {
                            console.error(e); // eslint-disable-line no-console
                        }
                    }
                }
            };
        }()),
        ad: function (ad, success) {
            var data = KBB.ads[ad],
                scriptUrl = '/js/kbb/ads/kbb.ads.{0}.js'.format(ad),
                isRequesting = false,
                isRequested = false; /* script already included */

            success = success || function () { };

            for (var i = 0; i < _ads.length; i++) {
                if (_ads[i].ad === ad) {
                    isRequesting = true;
                    isRequested = _ads[i].controller;
                    break;
                }
            }
            _ads.push({ ad: ad, cb: success, complete: isRequested, controller: isRequested });
            if (isRequesting) {
                if (isRequested) {
                    success(isRequested); /* use loaded controller */
                }
                return; /* let the original request handle */
            }

            /* Let's see if this ad has a controller in combres is loaded, this is somewhat of a hack for now */
            if (data && data.controller) {
                scriptUrl = data.controller;
            }

            $.ajax({
                url: scriptUrl,
                dataType: 'script',
                cache: true,
                success: function (data, status) {
                    if (status === 'success') {
                        var controller = KBB.get('ads.{0}Controller'.format(ad));
                        if (!controller) {
                            console.error('No AD controller for {0}'.format(ad)); // eslint-disable-line no-console
                            return;
                        }
                        for (var i = 0; i < _ads.length; i++) {
                            if (_ads[i].ad === ad) {
                                _ads[i].controller = controller;
                                if ($.isFunction(controller.init)) {
                                    controller.init.call(controller);
                                }
                                _ads[i].cb(controller);
                            }
                        }
                    }
                }
            });
        }
    };
}()));

KBB.extend(KBB, (function () {
    var _isModulesLoaded = false;

    function _init(ns) {
        for (var i in ns) {
            try {
                ns[i].init();
                KBB.events.fire('{0}.ready'.format(i));
            } catch (e) {
                console.error(e); // eslint-disable-line no-console
            }
        }
    }
    return {
        init: function () {
            _init(KBB.modules);
            _isModulesLoaded = true;
            KBB.events.fire('KBB.ready');
        },
        ready: function (cb) {
            if (!$.isFunction(cb)) {
                throw 'KBB.ready expects a valid callback/function';
            }
            if (_isModulesLoaded) {
                cb.call();
            } else {
                KBB.events.on('KBB.ready', cb);
            }
        }
    };
}()));

KBB.ads = KBB.ads || {};
/* Hopefully, we never have an adType called helpers ;) otherwise, this would be overwritten */
KBB.ads.helpers = (function () {
    var _types = {
            iframe: 'ifr',
            javascript: 'js'
        },
        sessionId,
        forEachAd = function (cb) {
            for (var ad in KBB.ads) {
                var obj = KBB.ads[ad];
                if (obj.type) {
                    cb(ad, obj);
                }
            }
        },
        generateNewUrl = function (existingUrl, newOrdValue, overrideOrd) {
            sessionId = sessionId || KBB.cookies.get('SessionId');
            var sprop17 = s.prop17,
                pi = 'pi=' + s.prop17;
        if (overrideOrd) {
                sprop17 = newOrdValue;
        }
            var returnUrl = existingUrl.replace(/ord=\d+/, 'ord=' + newOrdValue)
                               .replace(/pg=[\w|-]+/, 'pg=' + s.pageName)
                               .replace(new RegExp(sessionId + '\\w+'), sessionId + '_' + sprop17)
                               .replace(/u=\w+/, 'u=' + s.pageName)
                               .replace(/pi=\d+/, pi);

            return returnUrl;
        },
        getContainer = function (tagId, parentContainer) {
            var ad = KBB.ads[tagId];
        if (!ad || !ad.url) {
            return;
        }

            if (!!parentContainer && parentContainer.querySelector) {
                return ad.isFriendly ? parentContainer.querySelector('#iframe-' + tagId) : parentContainer.querySelector('#' + tagId);
            }
            return ad.isFriendly ? document.getElementById('iframe-' + tagId) : document.getElementById(tagId);
        };

    function getOrdValue() {
        return Math.random() * 1000000000000000000;
    }
    function getTimeStamp() {
        var epochTicks = 621355968000000000; // the number of .net ticks at the unix epoch
        var ticksPerMillisecond = 10000; // there are 10000 .net ticks per millisecond
        return epochTicks + ((new Date()).getTime() * ticksPerMillisecond); // calculate the total number of .net ticks for your date
    }

    function createNewAdTagFromOld(oldId, newId, oldSp, newSp) {
        KBB.ads[newId] = KBB.ads[oldId];
        KBB.ads[newId].url = KBB.ads[oldId].url.replace(oldSp, newSp);
    }

    return {
        getOrdValue: getOrdValue,
        createNewAdTagFromOld: createNewAdTagFromOld,

        loadAd: function (adUnit, dataAttribute, overrideOrd) {
            var ad = adUnit instanceof $ ? adUnit : $('#iframe-' + adUnit);
            if (!ad || !ad.length) {
                return;
            }
            var src = ad.data(dataAttribute || 'asrc');
            if (overrideOrd) {
                // new ord value if set for the friendly iframeads to change ord value for each impressions. new dfp changes requires new ord for every impression.
                var newurl = generateNewUrl(src, getOrdValue(), true);
                if (!newurl || !newurl.length) {
                    return;
                }
                ad[0].src = newurl;
            } else {
                if (!src || !src.length) {
                    return;
                }
                ad[0].src = src;
            }
        },
        isAdInView: function (tagId) {
            var ad = KBB.ads[tagId], parent, element, newElement;
            if (!ad || !ad.url || ad.type === _types.javascript) {
                return false;
            }
            var container = getContainer(tagId);
            if (!KBB.helpers.isElementInView(container)) {
                return false;
            }
            return true;
        },
        refreshGptAds: function () {
            //update PI value and refresh all initial load ads
            var dataLayer = KBB.Page.getDataLayer();
            dataLayer.pageinstance = s.prop17;
            KBB.Ads.refresh();
        },
        refreshAds: function (onlyRefreshVisibleAds, parentContainer) {
            var newOrdValue = getOrdValue();
            forEachAd(function(tagId) {
                KBB.ads.helpers.refreshAd(tagId, onlyRefreshVisibleAds, newOrdValue, parentContainer);
            });
        },
        refreshAd: function (tagId, onlyRefreshVisibleAd, newOrdValue, parentContainer) {
            var ad = KBB.ads[tagId], parent, element, newElement;
            if (!ad || !ad.url || ad.type === _types.javascript) {
                return false;
            }
            var container = getContainer(tagId, parentContainer);
            if (!container || onlyRefreshVisibleAd && !KBB.helpers.isElementInView(container)) {
                return;
            }
            ad.url = generateNewUrl(ad.url, newOrdValue, false);

            /* To prevent the ad refresh from adding to the browser history, the element needs to be replaced */
            if (ad.isFriendly) {
                /* TODO: need to change pagename correctly */
                element = document.getElementById('iframe-' + tagId);
                if (!element || !element.src.length) {
                    throw 'Friendly iFrame expected for' + tagId;
                }

                parent = element.parentElement;
                newElement = element.cloneNode(true);
                newElement.src = element.src.substring(0, element.src.indexOf('&jsSrc=')) + '&jsSrc=' + ad.url;

                if (ad.isSponsored) {
                    newElement.src = element.src.replace(/&issponsored=\d/, '&issponsored=' + ad.isSponsored);
                }

                parent.replaceChild(newElement, element);
            } else if (ad.type === _types.iframe) {
                element = document.getElementById(tagId);
                parent = element.parentElement;
                newElement = element.cloneNode(false);

                newElement.src = ad.url;
                parent.replaceChild(newElement, element);
            }
            return true;
        },
        hideAd: function (adTagId) {
            var container = $('[data-ad-container={0}]'.format(adTagId));
            if (container && container.length) {
                container.hide();
            }
        },
        getContainer: getContainer
    };
})();

KBB.ads.refresh = KBB.ads.helpers.refreshAds;

KBB.mvt = (function () {
    return {
        validTests: {},

        //DO NOT USE THESE FUNCTIONS.  They are purely for backwards compatibility
        addTest: function (id, testName) {
            if (typeof Utils !== 'undefined') {
                return Utils.tnt.addTest(id, testName);
            }
        },
        updateProp39: function () {
            if (typeof Utils !== 'undefined') {
                return Utils.tnt.updateProp39();
            }
        },
        getTestIds: function () {
            var array = [],
                persistedTests = this.getTestConfigsFromCookie(),
                combinedTests = (typeof Utils !== 'undefined' ? Utils.tnt.tests : {}),
                currentTestId,
                currentTest;

            if (persistedTests != undefined && persistedTests != {}) {
                jQuery.extend(combinedTests, persistedTests);
            }

            for (currentTestId in combinedTests) {
                currentTest = combinedTests[currentTestId];
                // If not already in the array and is also in the valid test ids array
                if (jQuery.inArray(currentTest.id, array) == -1) {
                    array.push(currentTest.id);
                }
            }
            return array;
        },
        getValidTestIds: function () {
            if (typeof this.validTests == 'undefined' || this.validTests == null) {
                return [];
            }

            var validTestIds = [],
                validTestId,
                validTest;
            for (validTestId in this.validTests) {
                validTest = this.validTests[validTestId];
                validTestIds.push(validTest.id);
            }
            return validTestIds;
        },
        addValidTests: function (validTestsStr) {
            /* Takes in a test array string with expiration dates in format "testid|expires^testid|expires^testid|expires^..." */
            if (typeof validTestsStr == 'undefined' || validTestsStr == null || validTestsStr.length == 0) {
                return;
            }

            var hasMultiple = validTestsStr.indexOf('^') > -1,
                i,
                currentValidTestStr,
                validTestArray;

            if (hasMultiple) {
                var validTestStrArray = validTestsStr.split('^');
                for (i = 0; i < validTestStrArray.length; i++) {
                    currentValidTestStr = validTestStrArray[i];
                    if (currentValidTestStr.indexOf('|') == -1) {
                        continue;
                    }
                    validTestArray = currentValidTestStr.split('|');
                    this.addValidTest(validTestArray[0], validTestArray[1]);
                }
            } else {
                if (validTestsStr.indexOf('|') == -1) {
                    return;
                }
                validTestArray = validTestsStr.split('|');
                this.addValidTest(validTestArray[0], validTestArray[1]);
            }
        },
        addValidTest: function (id, expiresStr) {
            var expiresDate = new Date(expiresStr);
            this.validTests[id] = { id: id, expires: expiresDate };
        },
        getTestConfigsFromCookie: function () {
            var encodedTestCookie = KBB.cookies.get('MultivariateTests'),
                persistentTestCookie;
            if (typeof encodedTestCookie == 'undefined' || encodedTestCookie == '') {
                return {};
            }
            persistentTestCookie = decodeURIComponent(encodedTestCookie);

            var rawTestConfigs = JSON.parse(persistentTestCookie),
                validTestIds = this.getValidTestIds(),
                i,
                currentTest,
                testConfigs = {},
                now = new Date();
            if (rawTestConfigs != null && rawTestConfigs != 'undefined') {
                for (i = 0; i < rawTestConfigs.length; i++) {
                    currentTest = rawTestConfigs[i];
                    currentTest.expires = new Date(currentTest.expires);
                    if (currentTest.expires > now && jQuery.inArray(currentTest.id, validTestIds) != -1) {
                        testConfigs[currentTest.id] = { id: currentTest.id };
                    }
                }
            }
            return testConfigs;
        },
        persistTestConfigsToCookie: function () {
            var testIds = this.getTestIds(),
                validTestId,
                currentTest,
                updatedTestArray = [],
                now = new Date(),
                lastExpirationDate = new Date(),
                updatedTestArrayStr,
                encodedTestArray;

            for (validTestId in this.validTests) {
                currentTest = this.validTests[validTestId];
                if (jQuery.inArray(currentTest.id, testIds) != -1 && currentTest.expires > now) {
                    updatedTestArray.push(currentTest);
                    if (lastExpirationDate < currentTest.expires) {
                        lastExpirationDate = currentTest.expires;
                    }
                }
            }
            updatedTestArrayStr = JSON.stringify(updatedTestArray);
            encodedTestArray = encodeURIComponent(updatedTestArrayStr);
            KBB.cookies.set('MultivariateTests', encodedTestArray, lastExpirationDate);
            this.updateProp39();
        }
    };
}());

KBB.helpers = (function () {
    // TODO: clean up/move device checks and move into .helpers.experience
    return {
        isTabletDevice: false,
        isSmartphoneDevice: false,
        isPrintPreview: window.location.toString().indexOf('printable=true') > 0,
        experience: function () {
            var dl = KBB.DataLayer[(KBB.DataLayer.length - 1)];
            return {
                isTablet: dl.omniture.pageversion === 't',
                isSmartPhone: isSmartphoneDevice,
                isDesktop: dl.omniture.pageversion !== 't'
                // other pageversion values for desktop
                // pageversion === "n" (next project)
                // pageversion === "c" (current)
            };
        },
        openWindow: function (url, name, winprops) {
            var win = window.open(url, name || KBB.helpers.randomString(), winprops);
            if (!win) {
                alert('popup blockers turned on');
                return false;
            } else if (parseInt(navigator.appVersion) >= 4) {
                win.focus();
            }
            return win;
        },
        openNewTab: function (url) {
            window.open(url, '_blank');
        },
        randomString: function (length, chars) {
            var chars = chars || '0123456789abcdefghiklmnopqrstuvwxyz',
                randomstring = '';
            length = length || 8;
            for (var i = 0; i < length; i++) {
                var rnum = Math.floor(Math.random() * chars.length);
                randomstring += chars.substring(rnum, rnum + 1);
            }
            return randomstring;
        },
        openPrintPage: function (link) {
            link = link && link.href && link.href.length ? link.href : (link || self.location.href);
            link = KBB.helpers.appendUrlParameter(link, 'Printable', 'true');
            link = KBB.helpers.appendUrlParameter(link, 'PreviousPageName', parent.s.pageName);
            link = link.toLowerCase();
            KBB.helpers.openWindow(link, undefined, 'width=850,height=500,scrollbars=yes,resizable=yes');
        },
        formatWithCommas: function (num, removeDecimal) {
            num += '';
            var sp = num.split('.'),
                f = sp[0],
                dec = sp.length > 1 ? '.' + sp[1] : '',
                reg = /(\d+)(\d{3})/;

            while (reg.test(f)) {
                f = f.replace(reg, '$1' + ',' + '$2');
            }

            return f + (removeDecimal ? '' : dec);
        },
        isElementInView: function (elem) {
            var _element = $(elem),
                _window = $(window),
                _winTop = _window.scrollTop(),
                _winBottom = _winTop + _window.height(),
                _elemTop = _element.offset().top,
                _elemBottom = _elemTop + _element.height();
            return _elemBottom >= _winTop && _elemTop <= _winBottom;
        },
        toProperCase: function (str) {
            return str.replace(/\w\S*/g, function(txt) {
                return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
            });
        },
        getUrlParameters: function (url) {
            var e,
                o = {},
                a = /\+/g,
                r = /([^&=]+)=?([^&]*)/g,
                d = function (s) { return decodeURIComponent(s.replace(a, ' ')); },
                q = url ? url.substring(url.indexOf('?') + 1) : self.location.search.substring(1);

            while (e = r.exec(q)) {
                o[d(e[1])] = d(e[2]);
            }
            return o;
        },
        updateUrlParameter: function (url, key, value, forceInsert) {
            var re = new RegExp('([?&])' + key + '=.*?(&|#|$)(.*)', 'gi');

            if (!forceInsert && re.test(url)) {
                if (value != null && value !== '') {
                    return url.replace(re, '$1' + key + '=' + value + '$2$3');
                }
                else {
                    var hash = url.split('#');
                    url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
                    if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
                        url += '#' + hash[1];
                    }
                    return url;
                }
            }
            else {
                if (value != null && value !== '' && typeof url !== 'undefined') {
                    var separator = url.indexOf('?') !== -1 ? '&' : '?',
                        hash = url.split('#');
                    url = hash[0] + separator + key + '=' + value;
                    if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
                        url += '#' + hash[1];
                    }
                    return url;
                }
                else {
                    return url;
                }
            }
        },
        appendUrlParameter: function (url, parameter, parametervalue) {
            return KBB.helpers.updateUrlParameter(url, parameter, parametervalue, true);
        },
        replaceUrlParameter: function (url, name, value) {
            return KBB.helpers.updateUrlParameter(url, name, value);
        },
        deleteUrlParameter: function (url, name) {
            return KBB.helpers.updateUrlParameter(url, name);
        },
        removeSpecialChars: function (str) {
            // reomve prefix '$' and suffix '%' and middle ','
            str = str.replace(/\,/g, '');
            str = str.replace(/\%/g, '');
            str = str.replace(/\$/g, '');
            return str;
        },
        isRetinaDisplay: function () {
            var hasIsTabletInUrl = (window.location.href.indexOf('tablet=on') !== -1);
            return (window.devicePixelRatio > 1) || hasIsTabletInUrl;
        },
        isNumericInput: function (input) {
            var type = input.getAttribute('type');
            return (type === 'tel' || type === 'number' || (type === 'text' && input.pattern && /^((\[0\-9\]|\\d)(\?|\+|\*|\{\d+(\:\d+)?\})?)+$/.test(input.pattern)));
        },
        parseTokens: function (text) {
            'use strict';
            // Taken from KBB.omniture.js since this is used by PETS to evaluate templated fields
            // use this so you dont need to use eval to parse stuff like "abc_${s.prop2}_btn"
            if (!text) {
                return '';
            }

            var matcher = /\$\{+([^}]+)\}+/;
            var matched;
            while ((matched = matcher.exec(text)) !== null) {
                text = text.replace(matched[0], KBB.helpers.evaluate(matched[1]));
            }
            return text.toLowerCase();
        },
        evaluate: function (func, caller) {
            'use strict';

            //Safely evaluate a string
            //Can execute a function with given params or simply return the evaulated variable
            //However, very limited in what it can do; cannot handle edge cases where params contain commas
            //since we split the list of params by comma
            //Does not evaulate the parameters either, treats everything like a string
            //For what we are using it for, these known limitations are fine

            if (!func || typeof func !== 'string') {
                return undefined;
            }

            var params = null;
            func = $.trim(func);
            if (func.endsWith(')')) {
                var parenIndex = func.indexOf('(');
                params = func.substring(parenIndex + 1, func.length - 1).split(',');
                func = func.substring(0, parenIndex);
            }

            var scope = window;
            var namespaces = func.split('.');

            for (var i = 0, length = namespaces.length; i < length; i++) {
                if (scope !== undefined && scope !== null) {
                    scope = scope[namespaces[i]];
                } else {
                    console.error('Aborting js evaluation, scope "' + namespaces[i - 1] + '" does not exist when evaluating "' + arguments[0] + '"'); // eslint-disable-line no-console
                    return undefined;
                }
            }

            if (params && scope) {
                return scope.apply(caller, params);
            } else {
                return scope;
            }
        },
        hideTooltips: function () {
            // find tooltips either:
            // tooltips shown by aTooltip or jQuery (using 'generic')
            // or shown by aTooltip but use custom class (e.g 'market-price-disclaimer-tooltip'), not '.generic'
            var tooltips = document.querySelectorAll('.generic, .js-custom-tooltip');
            for (var i = 0; i < tooltips.length; i++) {
                tooltips[i].style.display = 'none';
            }
        },
        hidePanels: function () {
            if (KBB.modules) { // make sure scripts related to KBB.modules are included
                if (KBB.modules.socialToolbar) {
                    KBB.modules.socialToolbar.hidePanels();
                }
                if (KBB.modules.headerShare) {
                    KBB.modules.headerShare.hideAll();
                }
            }
        },
        hideModals: function (currentJqm) {
            if ($.jqm) {
                for (var modal in $.jqm.hash) {
                    var isParent = $.jqm.hash[modal].w.has($(currentJqm));
                    // Check if modals are opening then close them
                    if (window.getComputedStyle($.jqm.hash[modal].w[0]).getPropertyValue('display') !== 'none' &&
                        !isParent) {
                        $.jqm.close(modal);
                    }
                }
            }
        },
        hideOverlays: function (currentJqm) {
            // If modal displayed then hide active tooltip, social toolbar, login panel, modal
            KBB.helpers.hideTooltips();
            KBB.helpers.hidePanels();
            KBB.helpers.hideModals(currentJqm);
        }
    };
}());
/* Define other namespaces here */
KBB.modules = KBB.modules || {};
KBB.social = KBB.social || {};
KBB.omniture = KBB.omniture || {};

KBB.zip = (function () {
    var regexValidZip = /^(\d{5}-\d{4})|(\d{5})$/;
    return {
        clear: function () {
            $(window).trigger('ZipCodeChanging');

            KBB.storage.removeFromCookie('PersistentZipCode');
            KBB.storage.removeFromCookie('ZipCode');

            $(window).trigger('ZipCodeChanged', ['']);
        },
        get: function () {
            return KBB.storage.getFromCookie('PersistentZipCode') || KBB.storage.getFromCookie('ZipCode');
        },
        set: function (zip) {
            var args = $.makeArray(arguments);

            zip = jQuery.trim(zip);

            $(window).trigger('ZipCodeChanging', args);

            if (!this.validateFormat(zip) || !this.validate(zip)) {
                return false;
            } else if (zip == KBB.zip.get()) {
                return true;
            }

            var success = KBB.zip.save(zip);

            $(window).trigger('ZipCodeChanged', args);

            return success;
        },
        save: function (zip) {
            return !!(KBB.storage.saveToCookie('PersistentZipCode', zip, 365) | KBB.storage.saveToCookie('ZipCode', zip));
        },
        validate: function (zip, isAysnc) {
            var validZip = false;
            var deferred = jQuery.ajax({
                url: validateZipUrl,
                data: { zip: zip },
                async: isAysnc || false,
                success: function (data) { validZip = data; }
            });
            return isAysnc ? deferred : validZip;
        },
        validateFormat: function (zip) {
            return !!zip && !!zip.length && regexValidZip.test(zip);
        },
        getZipInfo: function (zip, isAysnc) {
            var zipInfo = false;
            var deferred = jQuery.ajax({
                url: validateGetZipInfoUrl,
                data: { zip: zip || KBB.zip.get() },
                async: isAysnc || false,
                success: function (data) {
                    zipInfo = data;
                    if (isAysnc) {
                        if (!data || !data.IsValid) {
                            $.window.trigger('GeoCodeFailed', ['ZipFail', data && !data.IsValid ? 'Invalid zip code' : 'no data']);
                        }
                        $.window.trigger('GeoCodeComplete', [data]);
                    }
                },
                error: function (e) { $.window.trigger('GeoCodeFailed', ['ZipFail', e]); }
            });
            return isAysnc ? deferred : zipInfo;
        },
        lookup: function (coords) {
            if (!coords || !coords.latitude || !coords.longitude) {
                throw TypeError();
            }

            return jQuery.ajax({
                url: validateGetZipInfoByLLUrl,
                data: {
                    latitude: coords.latitude,
                    longitude: coords.longitude
                }
            }).fail(function (e) {
                $.window.trigger('GeoCodeFailed', ['ZipFail', e]);
            }).done(function (data) {
                if (!data || !data.IsValid) {
                    $.window.trigger('GeoCodeFailed', ['ZipFail', data && !data.IsValid ? 'Invalid zip code' : 'no data']);
                } else {
                    KBB.zip.set(data.Zip, coords);
                }
                $.window.trigger('GeoCodeComplete', [data]);
            });
        }
    };
})();

/*eslint-disable no-console */
//DEPRECIATED!!!! DO NOT USE KBB.log(), use console.log() instead!!
//Keeping it available to maintain compatibility with existing code that still uses KBB.log()
KBB.log = function () {
    'use strict';
    console.warn('KBB.log() is depreciated, please use the standard console.log() instead.');
    if (console.log.apply) {
        console.log.apply(console, arguments);
    }
    else {
        console.log(Array.prototype.join.call(arguments, ' '));
    }
};
/*eslint-enable no-console */

$.format = function (source) {
    'use strict';
    return String.prototype.format.apply(source, Array.prototype.slice.call(arguments, 1));
};

//String trim polyfill
if (!String.prototype.trim) {
    String.prototype.trim = function () {
        'use strict';
        return this.replace(/^\s+|\s+$/g, '');
    };
}

//String endsWith polyfill
if (!String.prototype.endsWith) {
    String.prototype.endsWith = function (searchString, position) {
        'use strict';
        position = (position || this.length) - searchString.length;
        var lastIndex = this.lastIndexOf(searchString);
        return lastIndex !== -1 && lastIndex === position;
    };
}

(function ($) {
    if (typeof $ === 'undefined') {
        return;
    }
    //Allow jQuery to continue with .ready() calls even if one fails
    $.fn.jQueryReady = $.fn.ready;
    $.fn.ready = function (fn) {
        'use strict';
        return $.fn.jQueryReady(function () {
            try {
                return fn.apply(this, arguments);
            } catch (e) {
                console.error(e); // eslint-disable-line no-console
                if (KBB.config.dev) {
                    //throw e;
                }
            }
        });
    };

    //Log ajax errors
    $.document.ajaxError(function (event, xhr, ajaxOptions, thrownError) {
        'use strict';
        console.error('[Ajax Error] Error: "{0} [{1}]" AjaxUrl: {2} AjaxData: {3}'.format(thrownError, xhr.status, ajaxOptions.url, JSON.stringify(ajaxOptions.data))); // eslint-disable-line no-console
    });

    //Restrict user input to only allow numbers
    $.document.on('keypress', 'input', function (event) {
        'use strict';
        if (KBB.helpers.isNumericInput(this)) {
            var key = event.which,
                key_backspace = 8,
                key_enterKey = 13,
                key_esc = 27,
                key_zero = 48,
                key_nine = 57;
            var allowed = !key || (key_zero <= key && key <= key_nine) || key === key_esc || key === key_enterKey || key === key_backspace;
            if (!allowed) {
                return false;
            }
        }
    });

    //Restrict user input to only allow numbers, catches paste
    $.document.on('change', 'input', function (event) {
        'use strict';
        if (KBB.helpers.isNumericInput(this)) {
            $(this).val($(this).val().replace(/[^\d]/g, ''));
        }
    });
})(jQuery);


// PLEASE DO NOT ADD GLOBAL FUNCTIONS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// If you need to add global functions, ask yourself why. Everything should be scoped to a namespace!
// If you still need to add them globally, add them to either KBB.Trident.Web\js\kbb.js or KBB.Trident.Web\js\kbb\KBB.legacy.js
// Not this file!!
;
//Global functions

/* Hide ads function */
KBB.ads.mHideByClassHistory = [];
var mHideByClass = function (className) {
    var module = jQuery('.' + className);
    if (module != null) {
        jQuery(module).hide();
        jQuery('html').addClass('collapse-' + className);
        if (className == 'mrecshowcase') {
            $('#Mrec-container').removeClass('with-showcase');
        }
        $(document).trigger('AdCollapsed', { adClass: className });
        KBB.ads.mHideByClassHistory.push(className);
    }
};

/* Allow access via urlParameters["myValue"], instead of KBB.modules.query.params */
/* DO NOT DO THIS! We deliberately namespace all of our functions! Saving stuff back to the global namespace defeats the entire purpose! */
window.urlParameters = KBB.helpers.getUrlParameters();

var OpenOverlay = function (content, overlayElem, width, height, mTop, mLeft, scroll) {
    /* TD* notes: to complete flexible overlay and move to a namespaced method
    // update OpenOverlay calls at ~\..ConfigEngine\Data\GlobalDefinitions\PartnerLinks\Default__DEFAULT.xml
    */
    // set defaults
    var ctype = 'iframe', // TD* planning to use for full version of overlay
        ww = $(window).width(),
        wh = $(window).height(),
        w = (ww < width) ? (ww * .96) : width,
        h = (wh < width) ? (wh * .92) : height,
        mt = (-h / 2), // TD* add or mTop
        ml = (-w / 2), // TD* add or mLeft
        scrl = scroll || 'auto';

    //this is being set for omniture purpose for the overlay to submit new pagenames. reset is being done in the end of this function.
    var parentPagename = s.pageName; // to reset the pagename to the parentpagename after the overlay is closed.
    var parentDetailpagename = s.prop2; // to reset the detailpagename to the parentdetailpagename after the overlay is closed.
    var parentSprop15 = s.prop15;// to reset the prop15 to the prop15 after the overlay is closed.
    var overlayPagename = 'vehhistovr';
    s.prop15 = parentPagename;
    reSubmitOmniture(overlayPagename, overlayPagename);

    // reseting to the parent page information for parent page omniture activity.
    s.pageName = parentPagename;
    s.prop2 = parentDetailpagename;
    s.prop15 = parentSprop15;
    return false;
};

var encHTML = function (html) {
    return html.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
};

var encURL = function (url) {
    return url.replace(/-/g, '_').replace(/ /g, '-').replace(/[^a-zA-Z0-9-_)]+/g, '').toLowerCase();
};


/* Legacy globals */
var openWindow = KBB.helpers.openWindow;
var NewWindow = function (url, myname, w, h, t, l, scroll, e) {
    KBB.helpers.openWindow(url, myname, 'height=' + h + ',width=' + w + ',top=' + t + ',left=' + l + ',scrollbars=' + scroll + ',toolbar=yes,status=yes,resizable');
    return false;
};
var NewWindowNR = function (url, myname, w, h, t, l, scroll) {
    KBB.helpers.openWindow(url, myname, 'height=' + h + ',width=' + w + ',top=' + t + ',left=' + l + ',scrollbars=' + scroll + ',toolbar=no');
    return false;
};

/* Open link in new tab */
var NewTab = function (url) {
    KBB.helpers.openNewTab(url);
};
;
/*

What you need to know:

//SAVING:
KBB.storage.set(name, value, expiration): Saves data only to cookie
KBB.storage.saveLarge(name, value, expiration): Saves to localstorage, then falls back to cookies, then to session storage (useful if saving large amounts of data since cookies has limited space)
KBB.storage.saveAll(name, value, expiration): Saves to all locations (cookies, localstorage and session storage) for max chance at retrieval. USE SPARINGLY, ITS EASY TO FILL UP ALL THE SPACE WITHOUT REALIZING IT!!!

KBB.storage.saveToCookie(name, value, expiration): Saves data only to cookie
KBB.storage.saveToStorage(name, value, expiration): Saves data only to localstorage and sessionstorage
KBB.storage.saveToLocalStorage(name, value, expiration): Saves data only to localstorage
KBB.storage.saveToSessionStorage(name, value, expiration): Saves data only to sessionstorage

//Notes about calling the save functions:
    Passing name and value are required. Expiration parameter is optional. If blank, defaults to 30 days.
    Expiration parameter can either be a number (as in number of days till expired) or a date object.
    The expiration parameter can also be empty string, 0, or 'session' if you want the data to last for the session only
    You can also pass in path and domain when saving to cookies, although for 99% cases, leave it blank to use the default values

//RETRIEVING:
KBB.storage.get(name): Retrieves data from any locations (cookies, localstorage and session storage)
KBB.storage.getFromCookie(name): Retrieves data only from cookie
KBB.storage.getFromStorage(name): Retrieves data only from localstorage and sessionstorage
KBB.storage.getFromLocalStorage(name): Retrieves data only from localstorage
KBB.storage.getFromSessionStorage(name): Retrieves data only from sessionstorage

//DELETEING:
KBB.storage.remove(name): Deletes data from all locations (cookies, localstorage and session storage)
KBB.storage.removeFromCookie(name): Deletes data only from cookie
KBB.storage.removeFromStorage(name): Deletes data only from localstorage and sessionstorage
KBB.storage.removeFromLocalStorage(name): Deletes data only from localstorage
KBB.storage.removeFromSessionStorage(name): Deletes data only from sessionstorage

//TESTS:
KBB.storage.enabled(): Tests if we can save and retrieve data from long term storage spots (cookies and localstorage)
KBB.storage.storageEnabled(): Tests if we can save to localstorage or sessionstorage
KBB.storage.localStorageEnabled(): Tests if we can save to localstorage
KBB.storage.sessionStorageEnabled(): Tests if we can save to sessionstorage

//TLDR:
Use KBB.storage.set(name, value, expiration) to save data (leave expiration blank if you want the default value)
Use KBB.storage.get(name) to retrieve data
Use KBB.storage.remove(name) to remove data

*/

var KBB = KBB || {};
KBB.storage = (function (undefined) {
    'use strict';
    var cookieFormat = '{0}={1};expires={2};path={3};domain={4}';
    var defaultExpirationInDays = 30;
    var isLocalStorageSupported;
    var isSessionStorageSupported;
    var isCookiesSupported;

    //Parameter can be a Date object, number (expiration in days), or string which parses into a number
    //If 0, empty string, or 'session', return session date
    //If null, undefined or not a valid type, use defaultExpirationInDays
    var getDateString = function (expiration, forCookie) {
        if (expiration === 0 || ((typeof expiration === 'string' || expiration instanceof String) && (expiration === '' || expiration.toLowerCase() === 'session'))) {
            if (forCookie) {
                return ''; //Empty expiration means session cookie
            } else {
                //For storage, set expiration date to one hour from now to simulate session
                expiration = new Date();
                expiration.setHours(expiration.getHours() + 1);
            }
        }

        if (!(expiration instanceof Date)) {
            expiration = parseFloat(expiration) || defaultExpirationInDays;
            expiration = new Date(new Date().getTime() + (expiration * 86400000));
        }

        return expiration.toGMTString();
    };

    var readCookie = function (name) {
        name += '=';
        var parts = document.cookie.split(/;\s*/);
        for (var i = 0, length = parts.length; i < length; i++) {
            var part = parts[i];
            if (part.indexOf(name) === 0) {
                return decodeURIComponent(part.substring(name.length));
            }
        }
        return null;
    };

    var setCookie = function (name, value, expiration, path, domain) {
        try {
            expiration = getDateString(expiration, true);
            path = path || '/';
            domain = domain || '.kbb.com';

            document.cookie = cookieFormat.format(name, encodeURIComponent(value), expiration, path, domain);
            return true;
        } catch (e) {
            // catch exceptions
        }
        return false;
    };

    var removeCookie = function (name, path, domain) {
        return setCookie(name, '', new Date(0), path, domain); //Remove cookie by setting it to an expired date
    };

    var saveToStorage = function (storage, name, value, expiration) {
        try {
            if (!!storage) {
                expiration = getDateString(expiration);
                var data = JSON.stringify({
                    value: value,
                    expiration: expiration
                });
                storage.setItem(name, data);
                return true;
            }
        } catch (e) {
            // catch exceptions
        }
        return false;
    };

    var getFromStorage = function (storage, name) {
        var data;
        try {
            if (!!storage) {
                data = storage.getItem(name);
                if (!!data) {
                    var parsed;
                    try {
                        parsed = JSON.parse(data);
                    } catch (e) {
                        return data;
                    }
                    if (!!parsed.expiration && !!parsed.value) {
                        if (new Date(Date.parse(parsed.expiration)) - new Date() > 0) { //Check for expiration
                            return parsed.value;
                        }
                        else {
                            removeFromStorage(storage, name);
                        }
                    } else {
                        return data;
                    }
                }
            }
        } catch (e) {
            // catch exceptions
        }
        return null;
    };

    var removeFromStorage = function (storage, name) {
        try {
            if (!!storage) {
                storage.removeItem(name);
                return true;
            }
        } catch (e) {
            // catch exceptions
        }
        return false;
    };

    var cookiesEnabled = function () {
        //Check if we can save to cookies
        if (isCookiesSupported === undefined) {
            var key = 'kbb_test_cookies';
            var value = 'testing_testing_cookies';
            setCookie(key, value, 1);
            isCookiesSupported = value === readCookie(key);
            removeCookie(key);
        }
        return isCookiesSupported;
    };

    var localStorageEnabled = function () {
        //Check if we can save to local storage
        try {
            if (isLocalStorageSupported === undefined) {
                var key = 'kbb_test_localstorage';
                var value = 'testing_testing_localstorage';
                saveToStorage(localStorage, key, value, 1);
                isLocalStorageSupported = value === getFromStorage(localStorage, key);
                removeFromStorage(localStorage, key);
            }
        } catch (e) {
            isLocalStorageSupported = false;
        }
        return isLocalStorageSupported;
    };

    var sessionStorageEnabled = function () {
        //Check if we can save to session storage
        try {
            if (isSessionStorageSupported === undefined) {
                var key = 'kbb_test_sessionstorage';
                var value = 'testing_testing_sessionstorage';
                saveToStorage(sessionStorage, key, value, 1);
                isSessionStorageSupported = value === getFromStorage(sessionStorage, key);
                removeFromStorage(sessionStorage, key);
            }
        } catch (e) {
            isSessionStorageSupported = false;
        }
        return isSessionStorageSupported;
    };

    return {
        set: function (name, value, expiration, path, domain) {
            return KBB.storage.saveToCookie(name, value, expiration, path, domain);
        },
        get: function (name) {
            //Try to find data from all locations (cookies, localstorage and session storage)
            return KBB.storage.getFromCookie(name) || KBB.storage.getFromStorage(name);
        },
        remove: function (name, path, domain) {
            //Remove data from all locations
            return !!(KBB.storage.removeFromCookie(name, path, domain) | KBB.storage.removeFromStorage(name));
        },
        saveLarge: function (name, value, expiration, path, domain) {
            //SaveLarge function saves data to local storage with fallback to cookies then session storage
            //This is useful when saving large amounts of data as cookies have a very limited storage size
            return KBB.storage.saveToLocalStorage(name, value, expiration) || KBB.storage.saveToCookie(name, value, expiration, path, domain) || KBB.storage.saveToSessionStorage(name, value, expiration);
        },
        saveAll: function (name, value, expiration, path, domain) {
            //SaveAll function saves data everywhere for maximum chance of retrieval
            //USE SPARINGLY, ITS EASY TO FILL UP ALL THE SPACE WITHOUT REALIZING IT!!!
            return !!(KBB.storage.saveToCookie(name, value, expiration, path, domain) | KBB.storage.saveToStorage(name, value, expiration));
        },
        saveToCookie: function (name, value, expiration, path, domain) {
            return cookiesEnabled() && setCookie(name, value, expiration, path, domain);
        },
        getFromCookie: function (name) {
            return readCookie(name);
        },
        removeFromCookie: function (name, path, domain) {
            return removeCookie(name, path, domain);
        },
        saveToStorage: function (name, value, expiration) {
            return !!(KBB.storage.saveToLocalStorage(name, value, expiration) | KBB.storage.saveToSessionStorage(name, value, expiration));
        },
        saveToLocalStorage: function (name, value, expiration) {
            return localStorageEnabled() && saveToStorage(localStorage, name, value, expiration);
        },
        saveToSessionStorage: function (name, value, expiration) {
            return sessionStorageEnabled() && saveToStorage(sessionStorage, name, value, expiration);
        },
        getFromStorage: function (name) {
            return KBB.storage.getFromLocalStorage(name) || KBB.storage.getFromSessionStorage(name);
        },
        getFromLocalStorage: function (name) {
            return localStorageEnabled() ? getFromStorage(localStorage, name) : null;
        },
        getFromSessionStorage: function (name) {
            return sessionStorageEnabled() ? getFromStorage(sessionStorage, name) : null;
        },
        removeFromStorage: function (name) {
            return !!(KBB.storage.removeFromLocalStorage(name) | KBB.storage.removeFromSessionStorage(name));
        },
        removeFromLocalStorage: function (name) {
            return localStorageEnabled() && removeFromStorage(localStorage, name);
        },
        removeFromSessionStorage: function (name) {
            return sessionStorageEnabled() && removeFromStorage(sessionStorage, name);
        },
        enabled: function () {
            //Check if we can save to cookies or storage
            return cookiesEnabled() || KBB.storage.storageEnabled();
        },
        cookiesEnabled: function () {
            return cookiesEnabled();
        },
        storageEnabled: function () {
            return localStorageEnabled() || sessionStorageEnabled();
        },
        localStorageEnabled: function () {
            return localStorageEnabled();
        },
        sessionStorageEnabled: function () {
            return sessionStorageEnabled();
        }
    };
})();

//KBB.cookies and KBB.cache have been deprecated. Please use KBB.storage instead. Mapping functions for compatibility purposes

KBB.cookies = {
    set: KBB.storage.saveToCookie,
    get: KBB.storage.getFromCookie,
    remove: KBB.storage.removeFromCookie,
    enabled: KBB.storage.cookiesEnabled
};

KBB.cache = {
    get: KBB.storage.getFromStorage,
    add: KBB.storage.saveToStorage,
    ajaxGet: function (url, data, callback) { //DO NOT USE THIS FUNCTION ANYMORE! JUST STICK WITH JQUERY's BUILT IN AJAX FUNCTIONS! Leaving code here to maintain compatibility with current code that still uses this function
        'use strict';
        console.warn('KBB.cache.ajaxGet() function is deprecated; if you want to cache an ajax call, just use $.ajax() and let the browser handle caching for you: ' + url); // eslint-disable-line no-console
        if ($.isFunction(callback)) {
            $.get(url, data, callback);
        } else {
            console.error('A valid callback was not supplied to KBB.cache.ajaxGet: ' + url); // eslint-disable-line no-console
        }
    }
};

(function () {
    'use strict';
    //Local storage tends to build up and never gets cleared out
    //So clear storage when assembly version or data version change
    if (KBB.storage.getFromStorage('kbb.assemblyVersion') != KBB.versions.assembly || KBB.storage.getFromStorage('kbb.dataVersion') != KBB.versions.data) {
        try {
            localStorage.clear();
            sessionStorage.clear();
            KBB.storage.saveToStorage('kbb.assemblyVersion', KBB.versions.assembly);
            KBB.storage.saveToStorage('kbb.dataVersion', KBB.versions.data);
        } catch (e) {
            // catch exception
        }
    }
})();
;
/* eslint-disable no-unused-vars */

var KBB = KBB || {};
KBB.helpers = KBB.helpers || {};
KBB.helpers.isTabletDevice = KBB.helpers.isTabletDevice || false;
KBB.helpers.isSmartphoneDevice = KBB.helpers.isSmartphoneDevice || false;

function PartnerLink(partner, pagename_description, ec_partnercode, o_this, om_events) {
    'use strict';

    var pageCallOverride;

    s = s_gi(s_account);

    /* Set omniture tracking properties */
    s.dynamicAccountList = s_account;
    if (ec_partnercode && !ec_partnercode.indexOf('kbbmain')) {
        ec_partnercode = '';
    }
    s.linkName = (pagename_description || '').toLowerCase();
    s.events = 'purchase' + (om_events ? (',' + om_events) : '');
    s.products = (ec_partnercode + ';' + partner + ':' + pagename_description + ';1;0.00').toLowerCase();
    s.prop18 = s.linkName;
    s.eVar2 = partner.toLowerCase();
    var clock = new Date();
    s.purchaseID = clock.getHours() + '.' + clock.getMinutes() + '.' + clock.getSeconds() + '.' + Math.random();
    // globals
    s.linkTrackVars = 'server,zip,products,events,purchaseID';
    // props
    s.linkTrackVars += ',prop2,prop4,prop7,prop17,prop18,prop25,prop26,prop27,prop28,prop33,prop39,prop41,prop42,prop43,prop58,prop53,prop32,eVar73';
    // eVars
    s.linkTrackVars += ',eVar2,eVar10,eVar11,eVar12,eVar22,eVar42,eVar58,eVar59,eVar60,eVar61,eVar74,eVar75';
    //Need to store Page Load time for partner PowerSport and Cyclecx
    if (partner === 'pwrsprtbuy' || partner === 'bkbndt' || partner === 'cyclecx') {
        s.linkTrackVars += ',eVar13';
    }


    s.linkTrackEvents = 'purchase' + (om_events ? (',' + om_events) : '');

    if (KBB.helpers.isTabletDevice) {
        // set for desktop pages viewed on tablet
        s.events += ',event16';
        s.linkTrackEvents += ',event16';

        // set for TOE pages
        if (!!KBB.Tablet && !!KBB.Tablet.Omniture) {
            KBB.Tablet.Omniture.setOmnitureClickValues();
            KBB.Tablet.Omniture.setOmnitureTrackings();
            KBB.Tablet.Omniture.copyOmniturePropsToVars();
        }
    }

    if (KBB && KBB.omniture) {
        pageCallOverride = KBB.omniture.setSValueElementOverrides(o_this, true);
    }

    if (pageCallOverride) {
        s.t();
    } else {
        s.tl(o_this, 'o', pagename_description.toLowerCase());
    }

    /* Clear omniture tracking properties */
    if (KBB && KBB.get('omniture.reset')) {
        KBB.omniture.reset(s);
    }
}

function MobilePartnerLink(action, o_this, om_events) {
    'use strict';

    var pageCallOverride;

    s = s_gi(s_account);

    /* Set omniture tracking properties */
    s.dynamicAccountList = s_account;
    s.events = om_events ? (om_events) : '';
    s.linkTrackVars = 'events,prop70,eVar2,eVar61,prop53,prop32,prop39,eVar73,eVar69';
    s.linkTrackEvents = 'event10,event11,event50,event52,event53,event54,event55,event56,event57,event58,event61,event62,event64,event71,event72,event73';

    if (KBB && KBB.omniture) {
        pageCallOverride = KBB.omniture.setSValueElementOverrides(o_this, true);
    }

    if (pageCallOverride) {
        s.t();
    } else {
        s.tl(o_this, 'o', action);
    }

    /* Clear omniture tracking properties */
    if (KBB && KBB.get('omniture.reset')) {
        KBB.omniture.reset(s);
    }
}

function AddPartnerClientImpression(partner, pagename_description, ec_partnercode, o_this, om_events) {
    'use strict';

    var pageCallOverride;

    //do not fire impressions for zip code overlay pages (when page name ends with "_zip")
    if (KBB && KBB.get('omniture.endsWithZip')) {
        if (KBB.omniture.endsWithZip(s.pageName)) {
            return;
        }
    }

    s = s_gi(s_account);
    s.dynamicAccountList = s_account;

    //initialize products
    s.products = '';

    s.products = (ec_partnercode + ';' + partner + ':' + pagename_description + ';1;0.00').toLowerCase();
    s.prop18 = ''; // clear out previous link names
    s.linkTrackVars = 'server,zip,prop2,prop4,prop7,prop25,prop26,prop27,prop28,prop18,eVar2,products,events,purchaseID,prop39,prop41,prop17,prop45,eVar12,prop24,prop53,prop32,eVar73,eVar69,eVar61,eVar74,eVar75';

    if (om_events) {
        s.linkTrackEvents = om_events;
        s.events = om_events;
    }

    if (KBB.helpers.isTabletDevice && !!KBB.Tablet && !!KBB.Tablet.Omniture) {
        KBB.Tablet.Omniture.setOmnitureTrackings();
        KBB.Tablet.Omniture.copyOmniturePropsToVars();
    }

    if (KBB && KBB.omniture) {
        pageCallOverride = KBB.omniture.setSValueElementOverrides(o_this);
    }

    if (pageCallOverride) {
        s.t();
    } else {
        s.tl(true, 'o', pagename_description.toLowerCase()); // use 'true' for  the first param to avoid 500ms delay for impressions
    }

    /* Clear omniture tracking properties */
    if (KBB && KBB.get('omniture.reset')) {
        KBB.omniture.reset(s);
    }
}

function AddPartnersClientImpression(products, o_this) {
    'use strict';

    //do not fire impressions for zip code overlay pages (when page name ends with "_zip")
    if (KBB && KBB.get('omniture.endsWithZip')) {
        if (KBB.omniture.endsWithZip(s.pageName)) {
            return;
        }
    }

    s = s_gi(s_account);
    s.dynamicAccountList = s_account;

    //initialize products
    s.products = '';

    s.products = products;
    s.linkTrackVars = 'server,zip,prop2,prop4,prop7,prop25,prop26,prop27,prop28,prop18,eVar2,products,events,purchaseID,prop39,prop41,prop45,eVar12,prop17,prop53,prop32,eVar73';

    if (KBB.helpers.isTabletDevice && !!KBB.Tablet && !!KBB.Tablet.Omniture) {
        KBB.Tablet.Omniture.setOmnitureTrackings();
        KBB.Tablet.Omniture.copyOmniturePropsToVars();
        KBB.Tablet.Omniture.setOmnitureImpressionValues();
    }

    s.tl(o_this, 'o', s.pageName.toLowerCase());

    /* Clear omniture tracking properties */
    if (KBB && KBB.get('omniture.reset')) {
        KBB.omniture.reset(s);
    }
}

function ResubmitPartnersClientImpression() {
    'use strict';

    //do not fire impressions for zip code overlay pages (when page name ends with "_zip")
    if (KBB && KBB.get('omniture.endsWithZip')) {
        if (KBB.omniture.endsWithZip(s.pageName)) {
            return;
        }
    }

    s = s_gi(s_account);
    s.dynamicAccountList = s_account;

    s.linkTrackVars = 'server,zip,prop2,prop4,prop7,prop25,prop26,prop27,prop28,prop18,eVar2,products,events,purchaseID,prop32,prop39,prop41,prop45,eVar12,prop17,prop53,prop32,eVar73';

    s.tl(true, 'o', s.pageName.toLowerCase());

    /* Clear omniture tracking properties */
    if (KBB && KBB.get('omniture.reset')) {
        KBB.omniture.reset(s);
    }
}

function reSubmitOmniture(pagename, detailedpagename, leadid, category, manufacturerid, modelid, vehicleid, yearid, compareids, subcategory) {
    'use strict';

    s = s_gi(s_account);
    s.pageName = pagename.toLowerCase();
    if (detailedpagename !== '') {
        s.prop2 = detailedpagename.toLowerCase();
    }
    if (leadid) {
        s.prop24 = leadid.toLowerCase();
    }
    if (category !== undefined && category !== null) {
        s.prop3 = category.toLowerCase();
    }
    if (subcategory !== undefined && subcategory !== null) {
        s.prop7 = subcategory.toLowerCase();
    }
    if (yearid !== undefined && yearid !== null) {
        s.prop4 = yearid;
    }
    if (manufacturerid !== undefined && manufacturerid !== null) {
        s.prop26 = manufacturerid;
    }
    if (modelid !== undefined && modelid !== null) {
        s.prop27 = modelid;
    }
    if (vehicleid !== undefined && vehicleid !== null) {
        s.prop28 = vehicleid;
    }
    if (compareids !== undefined && compareids !== null) {
        s.prop29 = compareids;
    }

    s.prop17 = IncrementSession();

    s.dynamicAccountList = s_account;
    s.t();

    /* Clear omniture tracking properties */
    if (KBB && KBB.get('omniture.reset')) {
        KBB.omniture.reset(s);
    }
}

function reSubmitOmnitureCallback(callback, pagename, detailedpagename, leadid, category, manufacturerid, modelid, vehicleid, yearid, compareids) {
    'use strict';

    s = s_gi(s_account);
    s.pageName = pagename.toLowerCase();
    if (detailedpagename !== '') {
        s.prop2 = detailedpagename.toLowerCase();
    }
    if (leadid) {
        s.prop24 = leadid.toLowerCase();
    }
    if (category !== undefined && category !== null) {
        s.prop3 = category.toLowerCase();
    }
    if (yearid !== undefined && yearid !== null) {
        s.prop4 = yearid;
    }
    if (manufacturerid !== undefined && manufacturerid !== null) {
        s.prop26 = manufacturerid;
    }
    if (modelid !== undefined && modelid !== null) {
        s.prop27 = modelid;
    }
    if (vehicleid !== undefined && vehicleid !== null) {
        s.prop28 = vehicleid;
    }
    if (compareids !== undefined && compareids !== null) {
        s.prop29 = compareids;
    }

    s.prop17 = IncrementSession();
    if (callback) {
        callback();
    }

    s.dynamicAccountList = s_account;
    s.t();

    /* Clear omniture tracking properties */
    if (KBB && KBB.get('omniture.reset')) {
        KBB.omniture.reset(s);
    }
}

function submitOmniture(o_this) {
    'use strict';

    s = s_gi(s_account);
    s.dynamicAccountList = s_account;

    if (o_this && KBB && KBB.omniture) {
        KBB.omniture.setSValueElementOverrides(o_this);
    }

    s.t();

    /* Clear omniture tracking properties */
    if (KBB && KBB.get('omniture.reset')) {
        KBB.omniture.reset(s);
    }
}

function pageView(pagename, detailedpagename) {
    'use strict';

    var trackVars = new Object();
    trackVars.pageName = pagename.toLowerCase();
    if (detailedpagename !== '') {
        trackVars.prop2 = detailedpagename.toLowerCase();
        trackVars.prop17 = IncrementSession();
    }
    s.t(trackVars);

    /* Clear omniture tracking properties */
    if (KBB && KBB.get('omniture.reset')) {
        KBB.omniture.reset(s);
    }
}

function IncrementSession() {
    'use strict';

    return (Math.random() * 10000000000000000).toFixed(0);
}

function AddPartner(partner, pagename_description, ec_partnercode) {
    'use strict';

    if (partner && partner.length > 0) {
        if (s.products && s.products.length > 0) {
            s.products += ',';
        }
        if (ec_partnercode && ec_partnercode.indexOf('kbbmain') < 0) {
            ec_partnercode = '';
        }
        s.products += (ec_partnercode + ';' + partner + ':' + pagename_description + ';1;0.00').toLowerCase();
    }
}

function AddPartnerImpressionBatch(partner, pagename_description, ec_partnercode) {
    'use strict';

    if (partner && partner.length > 0) {
        if (s.tempProducts && s.tempProducts.length > 0) {
            s.tempProducts += ',';
        }
        if (ec_partnercode && ec_partnercode.indexOf('kbbmain') < 0) {
            ec_partnercode = '';
        }
        s.tempProducts += ec_partnercode.toLowerCase() + ';' + partner.toLowerCase() + ':' + pagename_description.toLowerCase() + ';1;0.00';
    }

    if (KBB.helpers.isTabletDevice && !!KBB.Tablet && !!KBB.Tablet.Omniture) {
        KBB.Tablet.Omniture.setOmnitureTrackings();
        KBB.Tablet.Omniture.copyOmniturePropsToVars();
    }
}
;
/// <reference path="KBB\KBB.js" />
/*
Omniture Extensions for JavaScript.

----------------------------
--Partner Types Definition--
----------------------------
0 - partner click (Default)
1 - partner click and impression
3 - partner impression
4 - partner impression on click
99 - partner click and impression batch
100 - partner impression batch

------------------
--Explicit Calls--
------------------

[Click event is attached, via jQuery, to the body (Using .delegate(fn))]

<a href="#" data-omn-partner="nx"
data-omn-page="foo_${s.prop2}_lnk" />   -- Partner Click

<a href="#" data-omn-partner="nx"
data-omn-page="foo_${s.prop2}_lnk"
data-omn-type="1"
data-omn-onclick="MyFunction();" />     -- Client Impression & Partner Click
- w/ a custom event that will fire AFTER the PartnerClick event.

------------------
--Implicit calls--
------------------

KBB.omniture.impression
KBB.omniture.PartnerClick

The following example shows an Impression call from within a jQuery handler:
Assuming the data-omn-* attributes have been applied to the element:
...
$('a[data-omn-partner]').click(function()
{
KBB.omniture.impression.call(this);
return false;
});
...
Otherwise,
...
$('a[data-omn-partner]').click(function()
{
var omnitureType = 0, // Partner Click
omnitureDetails = new KBB.omniture.OmnitureDetails('nx', 'pagename', omnitureType);

KBB.omniture.impression.call(this, omnitureDetails);
return false;
});
...

-----------------
--jQuery Plugin--
-----------------

This is useful for instances when you already have a click event defined, which in turn
may; return false, stopPropagation, redirect etc.. anything that may stop the event from
bubbling up to the attached delegate. This will prevent the partner click from being called.

To solve this issue, provide a data-omn-onclick attribute with the element. Example:

<a href="#" data-omn-partner="nx"
data-omn-page="foo_${s.prop2}_lnk"
data-omn-onclick="MyMethod();" />
*/

/* globals AddPartner, AddPartnerImpressionBatch, AddPartnersClientImpression, AddPartnerClientImpression,
    ResubmitPartnersClientImpression, reSubmitOmniture, submitOmniture */

var KBB = KBB || {};
KBB.omniture = (function () {
    'use strict';

    function getPartnerLinkDetails() {
        var _this = $(this);

        if (!_this || !_this.length) {
            return undefined;
        }

        var pagename = this.getAttribute('data-omn-page'),
            partner = this.getAttribute('data-omn-partner'),
            events = this.getAttribute('data-omn-events'),
            type = this.getAttribute('data-omn-type'),
            action = this.getAttribute('data-omn-act'),
            mobileProp = KBB.helpers.isTabletDevice ? 'tablet' : undefined;

        return new KBB.omniture.OmnitureDetails(pagename, partner, type, events, mobileProp, action);
    }

    function onClickComplete(omnitureDetails, e) {
        var runScript = $(this).data('omn-onclick');

        if (typeof (runScript) !== 'undefined' && runScript !== false) {
            (new Function(runScript)).call({ obj: this, omniture: omnitureDetails, event: e });
        }
    }

    function getDefaultPartnerType() {
        return 'nx';
    }

    return {
        ParseTokens: function (page) {
            if (!page) {
                return '';
            }

            var matcher = /\$\{+([^}]+)\}+/;
            var matched;
            while ((matched = matcher.exec(page)) !== null) {
                page = page.replace(matched[0], KBB.helpers.evaluate(matched[1]));
            }
            return page.toLowerCase();
        },
        /* Object to hold our omniture variables */
        OmnitureDetails: function (page, partner, type, events, mobileProp, action) {
            if (mobileProp !== 'tablet' && (!page || !page.length)) {
                return;
            }

            this.page = KBB.omniture.ParseTokens(page);
            this.partner = (partner || getDefaultPartnerType()).toLowerCase();
            this.type = parseInt(type || 0);
            this.events = (events ? events.toLowerCase() : '');
            this.action = action;
        },
        PartnerImpression: function (event) {
            var o = typeof event !== 'undefined' && event instanceof KBB.omniture.OmnitureDetails
                         ? event : getPartnerLinkDetails.call(this);
            if (!o) {
                return;
            }

            KBB.omniture.impression(o.page, o.partner, this, undefined, o.events);
        },
        PartnerClick: function (event) {
            var e = event,
                o = typeof event !== 'undefined' && event instanceof KBB.omniture.OmnitureDetails
                    ? event : getPartnerLinkDetails.call(this),
                omnitureType = o ? parseInt(o.type) || 0 : 0;

            if (omnitureType > 3 && omnitureType < 99) { /* Are we firing an impression? */
                KBB.omniture.impression(o.page, o.partner, this, undefined, o.events);
            }
            if (omnitureType < 3 || omnitureType === 99) { /* Are we firing a partnerlink? */
                KBB.omniture.link(o.page, o.partner, this, o.events);
            }
            if ($(this).attr('data-omn-onclick')) {
                onClickComplete.call(this, o, e);
            }
        },
        AddPartner: function (event) {
            var o = typeof event !== 'undefined' && event instanceof KBB.omniture.OmnitureDetails
                         ? event : getPartnerLinkDetails.call(this);
            AddPartner(o.partner, o.page, '');
        },
        AddPartnerImpressionBatch: function (event) {
            var o = typeof event !== 'undefined' && event instanceof KBB.omniture.OmnitureDetails
                         ? event : getPartnerLinkDetails.call(this);
            AddPartnerImpressionBatch(o.partner, o.page, '');
        },
        PartnerBatchImpressionSubmit: function () {
            var batchPartnerImpressions = $('[data-omn-type="99"]:visible, [data-omn-type="100"]:visible');
            if (batchPartnerImpressions !== undefined && batchPartnerImpressions.length > 0) {
                KBB.omniture.submitAdditionalPartners(); //BZ-23996 - submit additional partners before clearing tempProducts
                s.tempProducts = '';

                batchPartnerImpressions.each(function (e) {
                    KBB.omniture.AddPartnerImpressionBatch.call(this, e);
                });
            }
        },
        /**
         * Triggers impressions using omniture data attributes on a module. Batch submits
         * impressions for optimization.
         * @method BatchImpressions
         * @param $module A jquery object that has elements with omniture data attributes
         * @param forVisible Flag to only batch visible elements
         * @public
         **/
        BatchImpressions: function ($module, forVisible) {
            var submit = false;

            $module.each(function () {
                $(this).find('[data-omn-page]').each(function () {
                    var $this = $(this);
                    var omnType = parseInt($this.attr('data-omn-type')) || 0;
                    if ((omnType === 1 || omnType === 3 || omnType === 100 || omnType === 99) && (forVisible !== true || $this.is(':visible'))) {
                        KBB.omniture.AddPartner.call(this);
                        submit = true;
                    }
                });
            });

            if (submit) {
                ResubmitPartnersClientImpression();
            }
        },
        resubmit: function (pagename, detailedpagename, leadid, category, manufacturerid, modelid, vehicleid, yearid, compareids) {
            //if we are detecting ad blockers then check for it before refiring omniture
            //here as this function is called in many locations and ad blocker detection needs to be before omniture submit on any refresh
            reSubmitOmniture(pagename || s.pageName, detailedpagename || s.prop2, leadid, category, manufacturerid, modelid, vehicleid, yearid, compareids);
            KBB.omniture.reset();

            if (KBB.Pixall) {
                KBB.Pixall.firePageLoadEvent();
            }
        },
        submit: function (o_this) {
            submitOmniture(o_this);
            KBB.omniture.reset();
        },
        impression: function (pagename_description, partner, o_this, ec_partnercode, om_events) {
            AddPartnerClientImpression(partner || getDefaultPartnerType(), pagename_description || s.prop2, ec_partnercode || '', o_this || this, om_events);
            KBB.omniture.reset();
        },
        link: function (page, partner, o_this, om_events) {
            PartnerLink(partner || getDefaultPartnerType(), page || s.prop2, '', o_this || this, om_events || '');
            KBB.omniture.reset();
        },
        reset: function (omnitureObject) {
            var obj = omnitureObject || s;

            if (obj.dynamicAccountList) {
                obj.dynamicAccountList = '';
            }
            if (obj.linkName) {
                obj.linkName = '';
            }
            if (obj.events) {
                obj.events = '';
            }
            if (obj.products) {
                obj.products = '';
            }
            if (obj.prop18) {
                obj.prop18 = '';
            }
            if (obj.prop33) {
                obj.prop33 = '';
            }
            if (obj.eVar2) {
                obj.eVar2 = '';
            }
            if (obj.linkTrackVars) {
                obj.linkTrackVars = '';
            }
            if (obj.linkTrackEvents) {
                obj.linkTrackEvents = '';
            }
            if (obj.purchaseID) {
                obj.purchaseID = '';
            }
            if (obj.eVar61) {
                if (KBB.helpers.isSmartphoneDevice) { //adblock
                    obj.eVar61 = '';
                }
            }
        },
        endsWithZip: function (pageName) {
            return pageName.endsWith('_zip');
        },
        submitAdditionalPartners: function () {
            //this function walks through s.tempProducts and submits partner client impressions in batches of about 600 characters each
            if (s.tempProducts && s.tempProducts.length > 0) {
                var arrProducts = s.tempProducts.split(',');
                var tempProducts = '';
                for (var i = 0; i < arrProducts.length; i++) {
                    if (tempProducts.length > 0) {
                        tempProducts = tempProducts + ',' + arrProducts[i];
                    } else {
                        tempProducts = arrProducts[i];
                    }
                    if (tempProducts.length > 600) {
                        if (typeof AddPartnersClientImpression === 'function') {
                            AddPartnersClientImpression(tempProducts, window);
                            tempProducts = '';
                        }
                    }
                }
                if (tempProducts.length > 0) {
                    if (typeof AddPartnersClientImpression === 'function') {
                        AddPartnersClientImpression(tempProducts, window);
                        tempProducts = '';
                    }
                }
            }
        },
        setSValueElementOverrides: function (element, link) {
            var returnValue = false;
            if (!element || element === window) {
                return returnValue;
            }
            var $element = $(element);

            // Special override data attribute that allows you to override any omniture value
            // JSON FORMAT: data-omn-svalues='{"prop2": "nccat-touch", "prop26": "54"}'
            //      VERY IMPORTANT: Key and Value strings are wrapped in double quotes, entire string in single quotes!!
            var sValueData = $element.data('omn-svalues');
            if (sValueData && $.isPlainObject(sValueData)) {
                for (var key in sValueData) {
                    if (sValueData.hasOwnProperty(key) && s.hasOwnProperty(key)) {
                        s[key] = sValueData[key];
                    }
                }
            }

            //Allow other functions to change omniture values before we fire the omniture call
            returnValue = $.window.triggerHandler('omnitureOverrides', { $element: $element, link: !!link });

            return returnValue || false;
        }
    };
})();

(function ($) {
    'use strict';

    $.document.ready(function () {
        var namespace = '.partnerLinks';
        var clickEvent = ($.getTouchEvent ? $.getTouchEvent() : 'click') + namespace;

        /* Wire up handler for all elements tagged with 'data-omn-page' */
        $.document.off(namespace).on(clickEvent, '[data-omn-page]:not(.disabled,.disable,[data-omn-act])', function () {
            KBB.omniture.PartnerClick.call(this);
        });

        setTimeout(function () {
            if (KBB.config.enableOmniture) {
                window.firedBatchedOmnitureImpressions = true;
                $('[data-omn-type="1"]:visible, [data-omn-type="3"]:visible').each(function (e) {
                    KBB.omniture.PartnerImpression.call(this);
                });
                KBB.omniture.PartnerBatchImpressionSubmit();
            }
        });
    });
}(jQuery));
;
/* TODO: Move this to KBB.ads.zipOverlayController
KBB.ads.zipOverlayController = (function () {
    return {
        init: function () {
        }
    }
})();
*/
function zipCodeBackOverlay(loc, sid, ref) { // eslint-disable-line no-unused-vars
    'use strict';

    var ps = loc.indexOf('#');
    if (ps > 0) {
        var pos = loc.lastIndexOf('zipo=');
        if (pos > 0) {
            var dsrest = loc.substr(pos).split('&');
            var zipo = dsrest[0].split('=');
            if (zipo[1] === sid) {
                location.href = ref;
                return;
            }
        }
    }
    else {
        location.href = location.href + '#zipo=' + sid;
    }
}

// zip code overlay ad
function zipAdExpandInit() { // eslint-disable-line no-unused-vars
    'use strict';

    var topPos = jQuery('#zipCodeContainer #zipCode').offset().top;

    jQuery('#zipCodeAd').css({
        'top': (topPos + jQuery('#zipCodeContainer #zipCode').height() - 32) + 'px'
    }).show();
}
;
var KBB = KBB || {};

KBB.sockets = function () {
    var intervalId,
        lastHash,
        cacheBust = 1,
        attachedCallback,
        window = this;

    return {
        send: function (message, targetUrl, target) {
            if (!targetUrl) {
                return;
            }

            target = target || parent; // default to parent

            try {
                if (window['postMessage']) {
                    // the browser supports window.postMessage, so call it with a targetOrigin
                    // set appropriately, based on the target_url parameter.
                    target['postMessage'](message, targetUrl.replace(/([^:]+:\/\/[^\/]+).*/, '$1'));
                } else if (targetUrl) {
                    // The browser does not support window.postMessage, so set the location
                    // of the target to target_url#message. A bit ugly, but it works! A cache
                    // bust parameter is added to ensure that repeat messages trigger the
                    // callback.
                    target.location = targetUrl.replace(/#.*$/, '') + '#' + (+new Date) + (cacheBust++) + '&' + message;
                }
            } catch (err) {
                // catch exception
            }
        },
        read: function (callback, sourceOrigin) {
            //browser supports window.postMessage
            if (window['postMessage']) {
                // bind the callback to the actual event associated with window.postMessage
                if (callback) {
                    attachedCallback = function (e) {
                        if ((typeof sourceOrigin === 'string' && e.origin !== sourceOrigin)
                                    || ($.isFunction(sourceOrigin) && !sourceOrigin(e.origin))) {
                            return false;
                        }
                        callback(e);
                    };
                }
                if (window['addEventListener']) {
                    window[callback ? 'addEventListener' : 'removeEventListener']('message', attachedCallback, false);
                } else {
                    window[callback ? 'attachEvent' : 'detachEvent']('onmessage', attachedCallback);
                }
            } else {
                // a polling loop is started & callback is called whenever the location.hash changes
                // Since the browser sucks, a polling loop will be started, and the
                // callback will be called whenever the location.hash changes.

                intervalId && clearInterval(intervalId);
                intervalId = null;

                if (callback) {
                    var delay = typeof sourceOrigin === 'number'
                        ? sourceOrigin
                        : 100;

                    intervalId = setInterval(function () {
                        var hash = document.location.hash,
                            re = /^#?\d+&/;
                        if (hash !== lastHash && re.test(hash)) {
                            lastHash = hash;
                            callback({ data: hash.replace(re, '') });
                        }
                    }, delay);
                }
            }
        }
    };
}();
;
/*
* jqModal - Minimalist Modaling with jQuery
*   (http://dev.iceburg.net/jquery/jqmodal/)
*
* Copyright (c) 2007,2008 Brice Burgess <bhb@iceburg.net>
* Dual licensed under the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
*
* $Version: 07/06/2008 +r13
*/
/*eslint-disable*/
(function ($) {
    $.fn.jqm = function (o) {
        var p = {
            overlay: 50,
            overlayClass: 'jqmOverlay',
            closeClass: 'jqmClose',
            trigger: '.jqModal',
            ajax: F,
            ajaxText: '',
            target: F,
            modal: F,
            toTop: F,
            onShow: F,
            onHide: F,
            onLoad: F
        };
        return this.each(function () {
            if (this._jqm) return H[this._jqm].c = $.extend({}, H[this._jqm].c, o); s++; this._jqm = s;
            H[s] = { c: $.extend(p, $.jqm.params, o), a: F, w: $(this).addClass('jqmID' + s), s: s };
            if (p.trigger) $(this).jqmAddTrigger(p.trigger);
        });
    };

    $.fn.jqmAddClose = function (e) { return hs(this, e, 'jqmHide'); };
    $.fn.jqmAddTrigger = function (e) { return hs(this, e, 'jqmShow'); };
    $.fn.jqmShow = function (t) { return this.each(function () { $.jqm.open(this._jqm, t); }); };
    $.fn.jqmHide = function (t) { return this.each(function () { $.jqm.close(this._jqm, t); }); };

    $.jqm = {
        hash: {},
        open: function (s, t) {
            var h = H[s], c = h.c, cc = '.' + c.closeClass, z = (parseInt(h.w.css('z-index'))), z = 2147483647, o = $('<div></div>').css({ height: '100%', width: '100%', position: 'fixed', left: 0, top: 0, 'z-index': z - 1, opacity: c.overlay / 100 }); if (h.a) return F; h.t = t; h.a = true; h.w.css('z-index', z);
            if (c.modal) { if (!A[0]) L('bind'); A.push(s); }
            else if (c.overlay > 0) h.w.jqmAddClose(o);
            else o = F;

            h.o = (o) ? o.addClass(c.overlayClass).prependTo('body') : F;
            if (ie6) { $('html,body').css({ height: '100%', width: '100%' }); if (o) { o = o.css({ position: 'absolute' })[0]; for (var y in { Top: 1, Left: 1 }) o.style.setExpression(y.toLowerCase(), '(_=(document.documentElement.scroll' + y + ' || document.body.scroll' + y + '))+"px"'); } }

            if (c.ajax) {
                var r = c.target || h.w, u = c.ajax, r = (typeof r == 'string') ? $(r, h.w) : $(r), u = (u.substr(0, 1) == '@') ? $(t).attr(u.substring(1)) : u;
                r.html(c.ajaxText).load(u, function () { if (c.onLoad) c.onLoad.call(this, h); if (cc) h.w.jqmAddClose($(cc, h.w)); e(h); });
            }
            else if (cc) h.w.jqmAddClose($(cc, h.w));

            if (c.toTop && h.o) h.w.before('<span id="jqmP' + h.w[0]._jqm + '"></span>').insertAfter(h.o);
            (c.onShow) ? c.onShow(h) : h.w.show(); e(h); return F;
        },
        close: function (s) {
            var h = H[s]; if (!h.a) return F; h.a = F;
            if (A[0]) { A.pop(); if (!A[0]) L('unbind'); }
            if (h.c.toTop && h.o) $('#jqmP' + h.w[0]._jqm).after(h.w).remove();
            if (h.c.onHide) h.c.onHide(h); else { h.w.hide(); if (h.o) h.o.remove(); } return F;
        },
        params: {}
    };
    var s = 0, H = $.jqm.hash, A = [], ie6 = $.browser.msie && ($.browser.version == '6.0'), F = false,
        i = $('<iframe src="javascript:false;document.write(\'\');" class="jqm"></iframe>').css({ opacity: 0 }),
        e = function (h) { if (ie6) if (h.o) h.o.html('<p style="width:100%;height:100%"/>').prepend(i); else if (!$('iframe.jqm', h.w)[0]) h.w.prepend(i); f(h); },
        f = function (h) { try { $(':input:visible', h.w)[0].focus(); } catch (_) { } },
        L = function (t) { $()[t]('keypress', m)[t]('keydown', m)[t]('mousedown', m); },
        m = function (e) { var h = H[A[A.length - 1]], r = (!$(e.target).parents('.jqmID' + h.s)[0]); if (r) f(h); return !r; },
        hs = function (w, t, c) {
            return w.each(function () {
                var s = this._jqm; $(t).each(function () {
                    if (!this[c]) { this[c] = []; $(this).click(function () { for (var i in { jqmShow: 1, jqmHide: 1 }) for (var s in this[i]) if (H[this[i][s]]) H[this[i][s]].w[i](this); return F; }); } this[c].push(s);
                });
            });
        };
})(jQuery);
/*eslint-enable*/
;
/*
* jqModal extension - customize jqModal methods
*/

window.addEventListener('load', function () {
    'use strict';

    var extJqmShow = $.fn.jqmShow;

    $.fn.jqmShow = function () {
        if (extJqmShow) {
            KBB.helpers.hideOverlays(this);
            return extJqmShow.apply(this, arguments);
        }
        return null;
    };
}, false);
;
// Leaderboard/Editorial Widget

var KBB = KBB || {};
KBB.modules = KBB.modules || {};
KBB.modules.leaderboardwidget = (function () {
    'use strict';

    return {
        init: function () {

            $(document).ready(function () {
                // leaderboard widget element virtually global, so checking every page for existence
                // do not fire if Zip Code overlay is available
                if (!$('#zipCodeContainer').is(':visible') && $('.lb-widget')) {
                    lbWidget();
                }
            });
        }
    };


    // leaderboard widget
    function lbWidget() {
        $('.lb-widget-nav a').on('click', function (e) {
            e.preventDefault();
            var slideNumber = $(this).attr('class').split('-')[2];
            PartnerLink('nx', 'navdot_' + s.prop2 + '_newsmod_' + slideNumber, '', this);
        });

        $('.lb-widget').jCarouselLite({
            btnGo: [
                '.widget-slide-1',
                '.widget-slide-2',
                '.widget-slide-3',
                '.widget-slide-4',
                '.widget-slide-5'
            ],

            hover: true,
            auto: 5000,
            speed: 0,

            circular: true,
            visible: 1,
            scroll: 1,

            afterEnd: function (actv) {
                $('.lb-widget-nav a').removeClass('active');
                $('.lb-widget-nav').find('a.widget-slide-' + $(actv).attr('carouselIndex')).addClass('active');
            }
        });

    }
})();
;
//v 1.0.0
(function (global, factory) { if (typeof exports === "object" && exports) { factory(exports) } else if (typeof define === "function" && define.amd) { define(["exports"], factory) } else { factory(global.Mustache = {}) } })(this, function (mustache) { var Object_toString = Object.prototype.toString; var isArray = Array.isArray || function (object) { return Object_toString.call(object) === "[object Array]" }; function isFunction(object) { return typeof object === "function" } function escapeRegExp(string) { return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&") } var RegExp_test = RegExp.prototype.test; function testRegExp(re, string) { return RegExp_test.call(re, string) } var nonSpaceRe = /\S/; function isWhitespace(string) { return !testRegExp(nonSpaceRe, string) } var entityMap = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;", "/": "&#x2F;" }; function escapeHtml(string) { return String(string).replace(/[&<>"'\/]/g, function (s) { return entityMap[s] }) } var whiteRe = /\s*/; var spaceRe = /\s+/; var equalsRe = /\s*=/; var curlyRe = /\s*\}/; var tagRe = /#|\^|\/|>|\{|&|=|!/; function parseTemplate(template, tags) { if (!template) return []; var sections = []; var tokens = []; var spaces = []; var hasTag = false; var nonSpace = false; function stripSpace() { if (hasTag && !nonSpace) { while (spaces.length) delete tokens[spaces.pop()] } else { spaces = [] } hasTag = false; nonSpace = false } var openingTagRe, closingTagRe, closingCurlyRe; function compileTags(tags) { if (typeof tags === "string") tags = tags.split(spaceRe, 2); if (!isArray(tags) || tags.length !== 2) throw new Error("Invalid tags: " + tags); openingTagRe = new RegExp(escapeRegExp(tags[0]) + "\\s*"); closingTagRe = new RegExp("\\s*" + escapeRegExp(tags[1])); closingCurlyRe = new RegExp("\\s*" + escapeRegExp("}" + tags[1])) } compileTags(tags || mustache.tags); var scanner = new Scanner(template); var start, type, value, chr, token, openSection; while (!scanner.eos()) { start = scanner.pos; value = scanner.scanUntil(openingTagRe); if (value) { for (var i = 0, valueLength = value.length; i < valueLength; ++i) { chr = value.charAt(i); if (isWhitespace(chr)) { spaces.push(tokens.length) } else { nonSpace = true } tokens.push(["text", chr, start, start + 1]); start += 1; if (chr === "\n") stripSpace() } } if (!scanner.scan(openingTagRe)) break; hasTag = true; type = scanner.scan(tagRe) || "name"; scanner.scan(whiteRe); if (type === "=") { value = scanner.scanUntil(equalsRe); scanner.scan(equalsRe); scanner.scanUntil(closingTagRe) } else if (type === "{") { value = scanner.scanUntil(closingCurlyRe); scanner.scan(curlyRe); scanner.scanUntil(closingTagRe); type = "&" } else { value = scanner.scanUntil(closingTagRe) } if (!scanner.scan(closingTagRe)) throw new Error("Unclosed tag at " + scanner.pos); token = [type, value, start, scanner.pos]; tokens.push(token); if (type === "#" || type === "^") { sections.push(token) } else if (type === "/") { openSection = sections.pop(); if (!openSection) throw new Error('Unopened section "' + value + '" at ' + start); if (openSection[1] !== value) throw new Error('Unclosed section "' + openSection[1] + '" at ' + start) } else if (type === "name" || type === "{" || type === "&") { nonSpace = true } else if (type === "=") { compileTags(value) } } openSection = sections.pop(); if (openSection) throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos); return nestTokens(squashTokens(tokens)) } function squashTokens(tokens) { var squashedTokens = []; var token, lastToken; for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { token = tokens[i]; if (token) { if (token[0] === "text" && lastToken && lastToken[0] === "text") { lastToken[1] += token[1]; lastToken[3] = token[3] } else { squashedTokens.push(token); lastToken = token } } } return squashedTokens } function nestTokens(tokens) { var nestedTokens = []; var collector = nestedTokens; var sections = []; var token, section; for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { token = tokens[i]; switch (token[0]) { case "#": case "^": collector.push(token); sections.push(token); collector = token[4] = []; break; case "/": section = sections.pop(); section[5] = token[2]; collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens; break; default: collector.push(token) } } return nestedTokens } function Scanner(string) { this.string = string; this.tail = string; this.pos = 0 } Scanner.prototype.eos = function () { return this.tail === "" }; Scanner.prototype.scan = function (re) { var match = this.tail.match(re); if (!match || match.index !== 0) return ""; var string = match[0]; this.tail = this.tail.substring(string.length); this.pos += string.length; return string }; Scanner.prototype.scanUntil = function (re) { var index = this.tail.search(re), match; switch (index) { case -1: match = this.tail; this.tail = ""; break; case 0: match = ""; break; default: match = this.tail.substring(0, index); this.tail = this.tail.substring(index) } this.pos += match.length; return match }; function Context(view, parentContext) { this.view = view == null ? {} : view; this.cache = { ".": this.view }; this.parent = parentContext } Context.prototype.push = function (view) { return new Context(view, this) }; Context.prototype.lookup = function (name) { var cache = this.cache; var value; if (name in cache) { value = cache[name] } else { var context = this, names, index; while (context) { if (name.indexOf(".") > 0) { value = context.view; names = name.split("."); index = 0; while (value != null && index < names.length) value = value[names[index++]] } else if (typeof context.view == "object") { value = context.view[name] } if (value != null) break; context = context.parent } cache[name] = value } if (isFunction(value)) value = value.call(this.view); return value }; function Writer() { this.cache = {} } Writer.prototype.clearCache = function () { this.cache = {} }; Writer.prototype.parse = function (template, tags) { var cache = this.cache; var tokens = cache[template]; if (tokens == null) tokens = cache[template] = parseTemplate(template, tags); return tokens }; Writer.prototype.render = function (template, view, partials) { var tokens = this.parse(template); var context = view instanceof Context ? view : new Context(view); return this.renderTokens(tokens, context, partials, template) }; Writer.prototype.renderTokens = function (tokens, context, partials, originalTemplate) { var buffer = ""; var self = this; function subRender(template) { return self.render(template, context, partials) } var token, value; for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { token = tokens[i]; switch (token[0]) { case "#": value = context.lookup(token[1]); if (!value) continue; if (isArray(value)) { for (var j = 0, valueLength = value.length; j < valueLength; ++j) { buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate) } } else if (typeof value === "object" || typeof value === "string") { buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate) } else if (isFunction(value)) { if (typeof originalTemplate !== "string") throw new Error("Cannot use higher-order sections without the original template"); value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender); if (value != null) buffer += value } else { buffer += this.renderTokens(token[4], context, partials, originalTemplate) } break; case "^": value = context.lookup(token[1]); if (!value || isArray(value) && value.length === 0) buffer += this.renderTokens(token[4], context, partials, originalTemplate); break; case ">": if (!partials) continue; value = isFunction(partials) ? partials(token[1]) : partials[token[1]]; if (value != null) buffer += this.renderTokens(this.parse(value), context, partials, value); break; case "&": value = context.lookup(token[1]); if (value != null) buffer += value; break; case "name": value = context.lookup(token[1]); if (value != null) buffer += mustache.escape(value); break; case "text": buffer += token[1]; break } } return buffer }; mustache.name = "mustache.js"; mustache.version = "1.0.0"; mustache.tags = ["{{", "}}"]; var defaultWriter = new Writer; mustache.clearCache = function () { return defaultWriter.clearCache() }; mustache.parse = function (template, tags) { return defaultWriter.parse(template, tags) }; mustache.render = function (template, view, partials) { return defaultWriter.render(template, view, partials) }; mustache.to_html = function (template, view, partials, send) { var result = mustache.render(template, view, partials); if (isFunction(send)) { send(result) } else { return result } }; mustache.escape = escapeHtml; mustache.Scanner = Scanner; mustache.Context = Context; mustache.Writer = Writer });;
KBB.createAndInit('KBB.ZipCode', function () {
    'use strict';

    var self = {};

    self.init = function () {
        document.addEventListener('DOMContentLoaded', function () {
            var datalayer = KBB.Page.getDataLayer(),
                location = datalayer.location;
            if (location) {
                var jsZipCodeClassQuery = '.js-zip-code-input',
                    jsCitiClassQuery = '.js-citi-text',
                    jsZipTextClassQuery = '.js-zip-text',
                    inputTextDefaultActiveClass = 'input-text-default-active',
                    zipCodeInputElements = document.querySelectorAll(jsZipCodeClassQuery),
                    citiTextElements = document.querySelectorAll(jsCitiClassQuery),
                    zipTexts = document.querySelectorAll(jsZipTextClassQuery),
                    zipCodeValue = location.zip ? location.zip : '',
                    citiValue = location.city ? 'Near: ' + location.city : '';

                if (zipCodeValue) {
                    [].slice.call(zipCodeInputElements).forEach(function (zipCodeInputElement) {
                        zipCodeInputElement.classList.remove(inputTextDefaultActiveClass);
                        zipCodeInputElement.value = zipCodeValue;
                    });

                    [].slice.call(zipTexts).forEach(function (zipText) {
                        zipText.innerHTML = zipCodeValue;
                    });
                }

                if (citiValue) {
                    [].slice.call(citiTextElements).forEach(function (citiTextElement) {
                        citiTextElement.innerHTML = citiValue;
                    });
                }
            }
        });
    };

    return self;
});
;
