· 6 years ago · Jan 20, 2020, 01:33 PM
1## Sniffed Detail - https://www.jdwilliams.co.uk/shop/signin/process.action
2
3### Request:
4
5POST /shop/signin/process.action HTTP/1.1
6Host: www.jdwilliams.co.uk
7Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
8MobileApp: 1
9Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
10Accept-Encoding: gzip, deflate
11Cache-Control: max-age=0
12Content-Type: application/x-www-form-urlencoded
13Content-Length: 129
14Origin: https://www.jdwilliams.co.uk
15Referer: https://www.jdwilliams.co.uk/shop/signin/display.action?mobileapp=true
16User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1
17Connection: keep-alive
18Cookie: ___utmvaaBuoDVX=Crv; incap_ses_47_827312=lgqdDjFOlB738+jnwvymAJaqJV4AAAAAIt4Ye+CYiSZaqrH9mpp3Cw==; visid_incap_827312=XuR3y8BpR0GYycJJ6Eb9MpaqJV4AAAAAQUIPAAAAAADFjMqyqNjlxrqDwoCLQ0/Y; JSESSIONID=0000AJ_yJDFwxf5b4NxaiD2p6vK:GH984-2; OEID_REGISTERED_CUSTOMER=true; secureToken=-565976678776451207
19
20accountRefOrEmail=jaka%40hmail%2Ecom&password=sjskjsjjs&csrfRandomFormToken=91be4d0d-5beb-4019-9f7d-80ef4060c089&isMobileApp=true
21
22### Response:
23
24HTTP/1.1 200 OK
25Date: Mon, 20 Jan 2020 13:26:48 GMT
26Vary: User-Agent
27Pragma: no-cache
28Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0, private
29Expires: Mon, 26 Jul 1997 05:00:00 GMT
30no-cache: no-cache
31Set-Cookie: OEID_REGISTERED_CUSTOMER=true; Max-Age=31536000; Path=/; HttpOnly
32LOGIN_PAGE: true
33P3P: CP="CAO DSP CURa ADMa DEVa TAIa OUR BUS IND UNI COM NAV INT"
34Keep-Alive: timeout=5
35Connection: Keep-Alive
36Content-Type: text/html; charset=UTF-8
37Content-Language: en-GB
38Content-Encoding: gzip
39Transfer-Encoding: chunked
40Set-Cookie: visid_incap_827312=XuR3y8BpR0GYycJJ6Eb9MpaqJV4AAAAAQUIPAAAAAADFjMqyqNjlxrqDwoCLQ0/Y; expires=Tue, 19 Jan 2021 08:05:18 GMT; path=/; Domain=.jdwilliams.co.uk
41Set-Cookie: incap_ses_47_827312=lgqdDjFOlB738+jnwvymAJaqJV4AAAAAIt4Ye+CYiSZaqrH9mpp3Cw==; path=/; Domain=.jdwilliams.co.uk
42Set-Cookie: ___utmvaaBuoDVX=a; Max-Age=0; path=/; expires=Sat, 11 Jan 2020 08:01:36 GMT
43X-CDN: Incapsula
44X-Iinfo: 3-113068380-113066999 SNNy RT(1579526806210 1520) q(0 0 0 -1) r(2 2) U6
45
46<!DOCTYPE html>
47<head>
48 <meta charset="utf-8">
49 <meta name="HandheldFriendly" content="True" />
50 <meta name="apple-mobile-web-app-capable" content="yes" />
51 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
52 <meta http-equiv="cleartype" content="on" />
53
54 <title>J D Williams</title>
55 <script type="text/javascript" src="https://images2.drct2u.com/dynamicPresentation/single/javascript/common/jquery-random/jquery-random.js?single_type=js&version=P-3-2020-01-07-WS-2020-01-V2&minify=true&appversion=0"></script>
56<meta name="jdw-isMobileDevice" value="true"/>
57<meta name="jdw-isStandardPCBrowser" value="false"/>
58<meta name="jdw-isTablet" value="false"/>
59<meta name="jdw-family" value="apple_iphone_ver9_1"/>
60<meta name="jdw-cutDownUserAgent" value="Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B5110e Safari/601.1"/>
61<meta property="fb:pages" content="503270076404440">
62<meta name="msvalidate.01" content="B13D26FA64A838856A44E2B707C08BFB"/><!-- standard page includes start, responsive sign in -->
63
64
65 <link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/dynamicPresentation/combine?combine_type=css&combine=desktop-header&version=P-3-2020-01-07-WS-2020-01-V2&minify=false&appversion=0" />
66 <link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/dynamicPresentation/combine?combine_type=css&combine=desktop-common&version=P-3-2020-01-07-WS-2020-01-V2&minify=false&appversion=0" />
67 <link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/dynamicPresentation/combine?combine_type=css&combine=desktop-siteNav&version=P-3-2020-01-07-WS-2020-01-V2&minify=false&appversion=0" />
68 <link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/dynamicPresentation/combine?combine_type=css&combine=common-modal&version=P-3-2020-01-07-WS-2020-01-V2&minify=false&appversion=0" />
69 <link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/dynamicPresentation/combine?combine_type=css&combine=common-modal2&version=P-3-2020-01-07-WS-2020-01-V2&minify=false&appversion=0" />
70 <link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/dynamicPresentation/combine?combine_type=css&combine=cookiepolicy-css&version=P-3-2020-01-07-WS-2020-01-V2&minify=false&appversion=0" />
71 <link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/dynamicPresentation/combine?combine_type=css&combine=gui-panels-css&version=P-3-2020-01-07-WS-2020-01-V2&minify=false&appversion=0" />
72 <link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/dynamicPresentation/combine?combine_type=css&combine=password-strength-css&version=P-3-2020-01-07-WS-2020-01-V2&minify=false&appversion=0" />
73 <link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/dynamicPresentation/combine?combine_type=css&combine=password-toggler-css&version=P-3-2020-01-07-WS-2020-01-V2&minify=false&appversion=0" />
74 <link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/dynamicPresentation/combine?combine_type=css&combine=gui-buttons-css&version=P-3-2020-01-07-WS-2020-01-V2&minify=false&appversion=0" />
75
76<link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/content/stylesheets/JDW_style.css" />
77 <link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/content/stylesheets/JDW_siteNav.css">
78 <script>var presentationVersion = "P-3-2020-01-07-WS-2020-01-V2";</script>
79<script>
80//XRegExp 2.0.0 <xregexp.com> MIT License
81var XRegExp;XRegExp=XRegExp||function(n){"use strict";function v(n,i,r){var u;for(u in t.prototype)t.prototype.hasOwnProperty(u)&&(n[u]=t.prototype[u]);return n.xregexp={captureNames:i,isNative:!!r},n}function g(n){return(n.global?"g":"")+(n.ignoreCase?"i":"")+(n.multiline?"m":"")+(n.extended?"x":"")+(n.sticky?"y":"")}function o(n,r,u){if(!t.isRegExp(n))throw new TypeError("type RegExp expected");var f=i.replace.call(g(n)+(r||""),h,"");return u&&(f=i.replace.call(f,new RegExp("["+u+"]+","g"),"")),n=n.xregexp&&!n.xregexp.isNative?v(t(n.source,f),n.xregexp.captureNames?n.xregexp.captureNames.slice(0):null):v(new RegExp(n.source,f),null,!0)}function a(n,t){var i=n.length;if(Array.prototype.lastIndexOf)return n.lastIndexOf(t);while(i--)if(n[i]===t)return i;return-1}function s(n,t){return Object.prototype.toString.call(n).toLowerCase()==="[object "+t+"]"}function d(n){return n=n||{},n==="all"||n.all?n={natives:!0,extensibility:!0}:s(n,"string")&&(n=t.forEach(n,/[^\s,]+/,function(n){this[n]=!0},{})),n}function ut(n,t,i,u){var o=p.length,s=null,e,f;y=!0;try{while(o--)if(f=p[o],(f.scope==="all"||f.scope===i)&&(!f.trigger||f.trigger.call(u))&&(f.pattern.lastIndex=t,e=r.exec.call(f.pattern,n),e&&e.index===t)){s={output:f.handler.call(u,e,i),match:e};break}}catch(h){throw h;}finally{y=!1}return s}function b(n){t.addToken=c[n?"on":"off"],f.extensibility=n}function tt(n){RegExp.prototype.exec=(n?r:i).exec,RegExp.prototype.test=(n?r:i).test,String.prototype.match=(n?r:i).match,String.prototype.replace=(n?r:i).replace,String.prototype.split=(n?r:i).split,f.natives=n}var t,c,u,f={natives:!1,extensibility:!1},i={exec:RegExp.prototype.exec,test:RegExp.prototype.test,match:String.prototype.match,replace:String.prototype.replace,split:String.prototype.split},r={},k={},p=[],e="default",rt="class",it={"default":/^(?:\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??)/,"class":/^(?:\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S]))/},et=/\$(?:{([\w$]+)}|(\d\d?|[\s\S]))/g,h=/([\s\S])(?=[\s\S]*\1)/g,nt=/^(?:[?*+]|{\d+(?:,\d*)?})\??/,ft=i.exec.call(/()??/,"")[1]===n,l=RegExp.prototype.sticky!==n,y=!1,w="gim"+(l?"y":"");return t=function(r,u){if(t.isRegExp(r)){if(u!==n)throw new TypeError("can't supply flags when constructing one RegExp from another");return o(r)}if(y)throw new Error("can't call the XRegExp constructor within token definition functions");var l=[],a=e,b={hasNamedCapture:!1,captureNames:[],hasFlag:function(n){return u.indexOf(n)>-1}},f=0,c,s,p;if(r=r===n?"":String(r),u=u===n?"":String(u),i.match.call(u,h))throw new SyntaxError("invalid duplicate regular expression flag");for(r=i.replace.call(r,/^\(\?([\w$]+)\)/,function(n,t){if(i.test.call(/[gy]/,t))throw new SyntaxError("can't use flag g or y in mode modifier");return u=i.replace.call(u+t,h,""),""}),t.forEach(u,/[\s\S]/,function(n){if(w.indexOf(n[0])<0)throw new SyntaxError("invalid regular expression flag "+n[0]);});f<r.length;)c=ut(r,f,a,b),c?(l.push(c.output),f+=c.match[0].length||1):(s=i.exec.call(it[a],r.slice(f)),s?(l.push(s[0]),f+=s[0].length):(p=r.charAt(f),p==="["?a=rt:p==="]"&&(a=e),l.push(p),++f));return v(new RegExp(l.join(""),i.replace.call(u,/[^gimy]+/g,"")),b.hasNamedCapture?b.captureNames:null)},c={on:function(n,t,r){r=r||{},n&&p.push({pattern:o(n,"g"+(l?"y":"")),handler:t,scope:r.scope||e,trigger:r.trigger||null}),r.customFlags&&(w=i.replace.call(w+r.customFlags,h,""))},off:function(){throw new Error("extensibility must be installed before using addToken");}},t.addToken=c.off,t.cache=function(n,i){var r=n+"/"+(i||"");return k[r]||(k[r]=t(n,i))},t.escape=function(n){return i.replace.call(n,/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")},t.exec=function(n,t,i,u){var e=o(t,"g"+(u&&l?"y":""),u===!1?"y":""),f;return e.lastIndex=i=i||0,f=r.exec.call(e,n),u&&f&&f.index!==i&&(f=null),t.global&&(t.lastIndex=f?e.lastIndex:0),f},t.forEach=function(n,i,r,u){for(var e=0,o=-1,f;f=t.exec(n,i,e);)r.call(u,f,++o,n,i),e=f.index+(f[0].length||1);return u},t.globalize=function(n){return o(n,"g")},t.install=function(n){n=d(n),!f.natives&&n.natives&&tt(!0),!f.extensibility&&n.extensibility&&b(!0)},t.isInstalled=function(n){return!!f[n]},t.isRegExp=function(n){return s(n,"regexp")},t.matchChain=function(n,i){return function r(n,u){for(var o=i[u].regex?i[u]:{regex:i[u]},f=[],s=function(n){f.push(o.backref?n[o.backref]||"":n[0])},e=0;e<n.length;++e)t.forEach(n[e],o.regex,s);return u===i.length-1||!f.length?f:r(f,u+1)}([n],0)},t.replace=function(i,u,f,e){var c=t.isRegExp(u),s=u,h;return c?(e===n&&u.global&&(e="all"),s=o(u,e==="all"?"g":"",e==="all"?"":"g")):e==="all"&&(s=new RegExp(t.escape(String(u)),"g")),h=r.replace.call(String(i),s,f),c&&u.global&&(u.lastIndex=0),h},t.split=function(n,t,i){return r.split.call(n,t,i)},t.test=function(n,i,r,u){return!!t.exec(n,i,r,u)},t.uninstall=function(n){n=d(n),f.natives&&n.natives&&tt(!1),f.extensibility&&n.extensibility&&b(!1)},t.union=function(n,i){var l=/(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g,o=0,f,h,c=function(n,t,i){var r=h[o-f];if(t){if(++o,r)return"(?<"+r+">"}else if(i)return"\\"+(+i+f);return n},e=[],r,u;if(!(s(n,"array")&&n.length))throw new TypeError("patterns must be a nonempty array");for(u=0;u<n.length;++u)r=n[u],t.isRegExp(r)?(f=o,h=r.xregexp&&r.xregexp.captureNames||[],e.push(t(r.source).source.replace(l,c))):e.push(t.escape(r));return t(e.join("|"),i)},t.version="2.0.0",r.exec=function(t){var r,f,e,o,u;if(this.global||(o=this.lastIndex),r=i.exec.apply(this,arguments),r){if(!ft&&r.length>1&&a(r,"")>-1&&(e=new RegExp(this.source,i.replace.call(g(this),"g","")),i.replace.call(String(t).slice(r.index),e,function(){for(var t=1;t<arguments.length-2;++t)arguments[t]===n&&(r[t]=n)})),this.xregexp&&this.xregexp.captureNames)for(u=1;u<r.length;++u)f=this.xregexp.captureNames[u-1],f&&(r[f]=r[u]);this.global&&!r[0].length&&this.lastIndex>r.index&&(this.lastIndex=r.index)}return this.global||(this.lastIndex=o),r},r.test=function(n){return!!r.exec.call(this,n)},r.match=function(n){if(t.isRegExp(n)){if(n.global){var u=i.match.apply(this,arguments);return n.lastIndex=0,u}}else n=new RegExp(n);return r.exec.call(n,this)},r.replace=function(n,r){var e=t.isRegExp(n),u,f,h,o;return e?(n.xregexp&&(u=n.xregexp.captureNames),n.global||(o=n.lastIndex)):n+="",s(r,"function")?f=i.replace.call(String(this),n,function(){var t=arguments,i;if(u)for(t[0]=new String(t[0]),i=0;i<u.length;++i)u[i]&&(t[0][u[i]]=t[i+1]);return e&&n.global&&(n.lastIndex=t[t.length-2]+t[0].length),r.apply(null,t)}):(h=String(this),f=i.replace.call(h,n,function(){var n=arguments;return i.replace.call(String(r),et,function(t,i,r){var f;if(i){if(f=+i,f<=n.length-3)return n[f]||"";if(f=u?a(u,i):-1,f<0)throw new SyntaxError("backreference to undefined group "+t);return n[f+1]||""}if(r==="$")return"$";if(r==="&"||+r==0)return n[0];if(r==="`")return n[n.length-1].slice(0,n[n.length-2]);if(r==="'")return n[n.length-1].slice(n[n.length-2]+n[0].length);if(r=+r,!isNaN(r)){if(r>n.length-3)throw new SyntaxError("backreference to undefined group "+t);return n[r]||""}throw new SyntaxError("invalid token "+t);})})),e&&(n.lastIndex=n.global?0:o),f},r.split=function(r,u){if(!t.isRegExp(r))return i.split.apply(this,arguments);var e=String(this),h=r.lastIndex,f=[],o=0,s;return u=(u===n?-1:u)>>>0,t.forEach(e,r,function(n){n.index+n[0].length>o&&(f.push(e.slice(o,n.index)),n.length>1&&n.index<e.length&&Array.prototype.push.apply(f,n.slice(1)),s=n[0].length,o=n.index+s)}),o===e.length?(!i.test.call(r,"")||s)&&f.push(""):f.push(e.slice(o)),r.lastIndex=h,f.length>u?f.slice(0,u):f},u=c.on,u(/\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4})|x(?![\dA-Fa-f]{2}))/,function(n,t){if(n[1]==="B"&&t===e)return n[0];throw new SyntaxError("invalid escape "+n[0]);},{scope:"all"}),u(/\[(\^?)]/,function(n){return n[1]?"[\\s\\S]":"\\b\\B"}),u(/(?:\(\?#[^)]*\))+/,function(n){return i.test.call(nt,n.input.slice(n.index+n[0].length))?"":"(?:)"}),u(/\\k<([\w$]+)>/,function(n){var t=isNaN(n[1])?a(this.captureNames,n[1])+1:+n[1],i=n.index+n[0].length;if(!t||t>this.captureNames.length)throw new SyntaxError("backreference to undefined group "+n[0]);return"\\"+t+(i===n.input.length||isNaN(n.input.charAt(i))?"":"(?:)")}),u(/(?:\s+|#.*)+/,function(n){return i.test.call(nt,n.input.slice(n.index+n[0].length))?"":"(?:)"},{trigger:function(){return this.hasFlag("x")},customFlags:"x"}),u(/\./,function(){return"[\\s\\S]"},{trigger:function(){return this.hasFlag("s")},customFlags:"s"}),u(/\(\?P?<([\w$]+)>/,function(n){if(!isNaN(n[1]))throw new SyntaxError("can't use integer as capture name "+n[0]);return this.captureNames.push(n[1]),this.hasNamedCapture=!0,"("}),u(/\\(\d+)/,function(n,t){if(!(t===e&&/^[1-9]/.test(n[1])&&+n[1]<=this.captureNames.length)&&n[1]!=="0")throw new SyntaxError("can't use octal escape or backreference to undefined group "+n[0]);return n[0]},{scope:"all"}),u(/\((?!\?)/,function(){return this.hasFlag("n")?"(?:":(this.captureNames.push(null),"(")},{customFlags:"n"}),typeof exports!="undefined"&&(exports.XRegExp=t),t}();
82//XRegExp Unicode Base 1.0.0
83(function(n){"use strict";function i(n){return n.replace(/[- _]+/g,"").toLowerCase()}function s(n){return n.replace(/\w{4}/g,"\\u$&")}function u(n){while(n.length<4)n="0"+n;return n}function f(n){return parseInt(n,16)}function r(n){return parseInt(n,10).toString(16)}function o(t){var e=[],i=-1,o;return n.forEach(t,/\\u(\w{4})(?:-\\u(\w{4}))?/,function(n){o=f(n[1]),o>i+1&&(e.push("\\u"+u(r(i+1))),o>i+2&&e.push("-\\u"+u(r(o-1)))),i=f(n[2]||n[1])}),i<65535&&(e.push("\\u"+u(r(i+1))),i<65534&&e.push("-\\uFFFF")),e.join("")}function e(n){return t["^"+n]||(t["^"+n]=o(t[n]))}var t={};n.install("extensibility"),n.addUnicodePackage=function(r,u){var f;if(!n.isInstalled("extensibility"))throw new Error("extensibility must be installed before adding Unicode packages");if(r)for(f in r)r.hasOwnProperty(f)&&(t[i(f)]=s(r[f]));if(u)for(f in u)u.hasOwnProperty(f)&&(t[i(u[f])]=t[i(f)])},n.addUnicodePackage({L:"0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05270531-055605590561-058705D0-05EA05F0-05F20620-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280840-085808A008A2-08AC0904-0939093D09500958-09610971-09770979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10CF10CF20D05-0D0C0D0E-0D100D12-0D3A0D3D0D4E0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC-0EDF0F000F40-0F470F49-0F6C0F88-0F8C1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510C710CD10D0-10FA10FC-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1BBA-1BE51C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11CF51CF61D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209C21022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2CF22CF32D00-2D252D272D2D2D30-2D672D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31BA31F0-31FF3400-4DB54E00-9FCCA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78B-A78EA790-A793A7A0-A7AAA7F8-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDAAE0-AAEAAAF2-AAF4AB01-AB06AB09-AB0EAB11-AB16AB20-AB26AB28-AB2EABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC"},{L:"Letter"}),n.addToken(/\\([pP]){(\^?)([^}]*)}/,function(n,r){var f=n[1]==="P"||n[2]?"^":"",u=i(n[3]);if(n[1]==="P"&&n[2])throw new SyntaxError("invalid double negation \\P{^");if(!t.hasOwnProperty(u))throw new SyntaxError("invalid or unknown Unicode property "+n[0]);return r==="class"?f?e(u):t[u]:"["+f+t[u]+"]"},{scope:"all"})})(XRegExp);
84//XRegExp Unicode Categories 1.2.0
85(function(n){"use strict";if(!n.addUnicodePackage)throw new ReferenceError("Unicode Base must be loaded before Unicode Categories");n.install("extensibility"),n.addUnicodePackage({Ll:"0061-007A00B500DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F05210523052505270561-05871D00-1D2B1D6B-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7B2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2CF32D00-2D252D272D2DA641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA661A663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CA78EA791A793A7A1A7A3A7A5A7A7A7A9A7FAFB00-FB06FB13-FB17FF41-FF5A",Lu:"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E05200522052405260531-055610A0-10C510C710CD1E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CED2CF2A640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA660A662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BA78DA790A792A7A0A7A2A7A4A7A6A7A8A7AAFF21-FF3A",Lt:"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC",Lm:"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D6A1D781D9B-1DBF2071207F2090-209C2C7C2C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A7F8A7F9A9CFAA70AADDAAF3AAF4FF70FF9EFF9F",Lo:"00AA00BA01BB01C0-01C3029405D0-05EA05F0-05F20620-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150840-085808A008A2-08AC0904-0939093D09500958-09610972-09770979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10CF10CF20D05-0D0C0D0E-0D100D12-0D3A0D3D0D4E0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC-0EDF0F000F40-0F470F49-0F6C0F88-0F8C1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA10FD-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1BBA-1BE51C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF11CF51CF62135-21382D30-2D672D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31BA31F0-31FF3400-4DB54E00-9FCCA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCAAE0-AAEAAAF2AB01-AB06AB09-AB0EAB11-AB16AB20-AB26AB28-AB2EABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",M:"0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065F067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0859-085B08E4-08FE0900-0903093A-093C093E-094F0951-0957096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F8D-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135D-135F1712-17141732-1734175217531772177317B4-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAD1BE6-1BF31C24-1C371CD0-1CD21CD4-1CE81CED1CF2-1CF41DC0-1DE61DFC-1DFF20D0-20F02CEF-2CF12D7F2DE0-2DFF302A-302F3099309AA66F-A672A674-A67DA69FA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1AAEB-AAEFAAF5AAF6ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26",Mn:"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065F067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0859-085B08E4-08FE0900-0902093A093C0941-0948094D0951-095709620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F8D-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135D-135F1712-17141732-1734175217531772177317B417B517B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91BAB1BE61BE81BE91BED1BEF-1BF11C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1CF41DC0-1DE61DFC-1DFF20D0-20DC20E120E5-20F02CEF-2CF12D7F2DE0-2DFF302A-302D3099309AA66FA674-A67DA69FA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1AAECAAEDAAF6ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26",Mc:"0903093B093E-09400949-094C094E094F0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1BAC1BAD1BE71BEA-1BEC1BEE1BF21BF31C24-1C2B1C341C351CE11CF21CF3302E302FA823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BAAEBAAEEAAEFAAF5ABE3ABE4ABE6ABE7ABE9ABEAABEC",Me:"0488048920DD-20E020E2-20E4A670-A672",N:"0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0B72-0B770BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293248-324F3251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",Nd:"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19D91A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",Nl:"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF",No:"00B200B300B900BC-00BE09F4-09F90B72-0B770BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F919DA20702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293248-324F3251-325F3280-328932B1-32BFA830-A835",P:"0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100A700AB00B600B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E085E0964096509700AF00DF40E4F0E5A0E5B0F04-0F120F140F3A-0F3D0F850FD0-0FD40FD90FDA104A-104F10FB1360-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A194419451A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601BFC-1BFF1C3B-1C3F1C7E1C7F1CC0-1CC71CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2D702E00-2E2E2E30-2E3B3001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFAAF0AAF1ABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65",Pd:"002D058A05BE140018062010-20152E172E1A2E3A2E3B301C303030A0FE31FE32FE58FE63FF0D",Ps:"0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62",Pe:"0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63",Pi:"00AB2018201B201C201F20392E022E042E092E0C2E1C2E20",Pf:"00BB2019201D203A2E032E052E0A2E0D2E1D2E21",Pc:"005F203F20402054FE33FE34FE4D-FE4FFF3F",Po:"0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100A700B600B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E085E0964096509700AF00DF40E4F0E5A0E5B0F04-0F120F140F850FD0-0FD40FD90FDA104A-104F10FB1360-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A194419451A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601BFC-1BFF1C3B-1C3F1C7E1C7F1CC0-1CC71CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2D702E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E30-2E393001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFAAF0AAF1ABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65",S:"0024002B003C-003E005E0060007C007E00A2-00A600A800A900AC00AE-00B100B400B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F60482058F0606-0608060B060E060F06DE06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0D790E3F0F01-0F030F130F15-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F1390-139917DB194019DE-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B9210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23F32400-24262440-244A249C-24E92500-26FF2701-27672794-27C427C7-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-324732503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FBB2-FBC1FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD",Sm:"002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C21182140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC",Sc:"002400A2-00A5058F060B09F209F309FB0AF10BF90E3F17DB20A0-20B9A838FDFCFE69FF04FFE0FFE1FFE5FFE6",Sk:"005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFBB2-FBC1FF3EFF40FFE3",So:"00A600A900AE00B00482060E060F06DE06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0D790F01-0F030F130F15-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F1390-1399194019DE-19FF1B61-1B6A1B74-1B7C210021012103-210621082109211421162117211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23F32400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26FF2701-27672794-27BF2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-324732503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD",Z:"002000A01680180E2000-200A20282029202F205F3000",Zs:"002000A01680180E2000-200A202F205F3000",Zl:"2028",Zp:"2029",C:"0000-001F007F-009F00AD03780379037F-0383038B038D03A20528-05300557055805600588058B-058E059005C8-05CF05EB-05EF05F5-0605061C061D06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F085C085D085F-089F08A108AD-08E308FF097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B78-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D3B0D3C0D450D490D4F-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EE0-0EFF0F480F6D-0F700F980FBD0FCD0FDB-0FFF10C610C8-10CC10CE10CF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B135C137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BF4-1BFB1C38-1C3A1C4A-1C4C1C80-1CBF1CC8-1CCF1CF7-1CFF1DE7-1DFB1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F209D-209F20BA-20CF20F1-20FF218A-218F23F4-23FF2427-243F244B-245F27002B4D-2B4F2B5A-2BFF2C2F2C5F2CF4-2CF82D262D28-2D2C2D2E2D2F2D68-2D6E2D71-2D7E2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E3C-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31BB-31BF31E4-31EF321F32FF4DB6-4DBF9FCD-9FFFA48D-A48FA4C7-A4CFA62C-A63FA698-A69EA6F8-A6FFA78FA794-A79FA7AB-A7F7A82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAF7-AB00AB07AB08AB0FAB10AB17-AB1FAB27AB2F-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBC2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF",Cc:"0000-001F007F-009F",Cf:"00AD0600-060406DD070F200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB",Co:"E000-F8FF",Cs:"D800-DFFF",Cn:"03780379037F-0383038B038D03A20528-05300557055805600588058B-058E059005C8-05CF05EB-05EF05F5-05FF0605061C061D070E074B074C07B2-07BF07FB-07FF082E082F083F085C085D085F-089F08A108AD-08E308FF097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B78-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D3B0D3C0D450D490D4F-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EE0-0EFF0F480F6D-0F700F980FBD0FCD0FDB-0FFF10C610C8-10CC10CE10CF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B135C137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BF4-1BFB1C38-1C3A1C4A-1C4C1C80-1CBF1CC8-1CCF1CF7-1CFF1DE7-1DFB1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F209D-209F20BA-20CF20F1-20FF218A-218F23F4-23FF2427-243F244B-245F27002B4D-2B4F2B5A-2BFF2C2F2C5F2CF4-2CF82D262D28-2D2C2D2E2D2F2D68-2D6E2D71-2D7E2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E3C-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31BB-31BF31E4-31EF321F32FF4DB6-4DBF9FCD-9FFFA48D-A48FA4C7-A4CFA62C-A63FA698-A69EA6F8-A6FFA78FA794-A79FA7AB-A7F7A82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAF7-AB00AB07AB08AB0FAB10AB17-AB1FAB27AB2F-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBC2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF"},{Ll:"Lowercase_Letter",Lu:"Uppercase_Letter",Lt:"Titlecase_Letter",Lm:"Modifier_Letter",Lo:"Other_Letter",M:"Mark",Mn:"Nonspacing_Mark",Mc:"Spacing_Mark",Me:"Enclosing_Mark",N:"Number",Nd:"Decimal_Number",Nl:"Letter_Number",No:"Other_Number",P:"Punctuation",Pd:"Dash_Punctuation",Ps:"Open_Punctuation",Pe:"Close_Punctuation",Pi:"Initial_Punctuation",Pf:"Final_Punctuation",Pc:"Connector_Punctuation",Po:"Other_Punctuation",S:"Symbol",Sm:"Math_Symbol",Sc:"Currency_Symbol",Sk:"Modifier_Symbol",So:"Other_Symbol",Z:"Separator",Zs:"Space_Separator",Zl:"Line_Separator",Zp:"Paragraph_Separator",C:"Other",Cc:"Control",Cf:"Format",Co:"Private_Use",Cs:"Surrogate",Cn:"Unassigned"})})(XRegExp);
86//XRegExp Unicode Scripts 1.2.0
87(function(n){"use strict";if(!n.addUnicodePackage)throw new ReferenceError("Unicode Base must be loaded before Unicode Scripts");n.install("extensibility"),n.addUnicodePackage({Arabic:"0600-06040606-060B060D-061A061E0620-063F0641-064A0656-065E066A-066F0671-06DC06DE-06FF0750-077F08A008A2-08AC08E4-08FEFB50-FBC1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFCFE70-FE74FE76-FEFC",Armenian:"0531-05560559-055F0561-0587058A058FFB13-FB17",Balinese:"1B00-1B4B1B50-1B7C",Bamum:"A6A0-A6F7",Batak:"1BC0-1BF31BFC-1BFF",Bengali:"0981-09830985-098C098F09900993-09A809AA-09B009B209B6-09B909BC-09C409C709C809CB-09CE09D709DC09DD09DF-09E309E6-09FB",Bopomofo:"02EA02EB3105-312D31A0-31BA",Braille:"2800-28FF",Buginese:"1A00-1A1B1A1E1A1F",Buhid:"1740-1753",Canadian_Aboriginal:"1400-167F18B0-18F5",Cham:"AA00-AA36AA40-AA4DAA50-AA59AA5C-AA5F",Cherokee:"13A0-13F4",Common:"0000-0040005B-0060007B-00A900AB-00B900BB-00BF00D700F702B9-02DF02E5-02E902EC-02FF0374037E038503870589060C061B061F06400660-066906DD096409650E3F0FD5-0FD810FB16EB-16ED173517361802180318051CD31CE11CE9-1CEC1CEE-1CF31CF51CF62000-200B200E-2064206A-20702074-207E2080-208E20A0-20B92100-21252127-2129212C-21312133-214D214F-215F21892190-23F32400-24262440-244A2460-26FF2701-27FF2900-2B4C2B50-2B592E00-2E3B2FF0-2FFB3000-300430063008-30203030-3037303C-303F309B309C30A030FB30FC3190-319F31C0-31E33220-325F327F-32CF3358-33FF4DC0-4DFFA700-A721A788-A78AA830-A839FD3EFD3FFDFDFE10-FE19FE30-FE52FE54-FE66FE68-FE6BFEFFFF01-FF20FF3B-FF40FF5B-FF65FF70FF9EFF9FFFE0-FFE6FFE8-FFEEFFF9-FFFD",Coptic:"03E2-03EF2C80-2CF32CF9-2CFF",Cyrillic:"0400-04840487-05271D2B1D782DE0-2DFFA640-A697A69F",Devanagari:"0900-09500953-09630966-09770979-097FA8E0-A8FB",Ethiopic:"1200-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A135D-137C1380-13992D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDEAB01-AB06AB09-AB0EAB11-AB16AB20-AB26AB28-AB2E",Georgian:"10A0-10C510C710CD10D0-10FA10FC-10FF2D00-2D252D272D2D",Glagolitic:"2C00-2C2E2C30-2C5E",Greek:"0370-03730375-0377037A-037D038403860388-038A038C038E-03A103A3-03E103F0-03FF1D26-1D2A1D5D-1D611D66-1D6A1DBF1F00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FC41FC6-1FD31FD6-1FDB1FDD-1FEF1FF2-1FF41FF6-1FFE2126",Gujarati:"0A81-0A830A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABC-0AC50AC7-0AC90ACB-0ACD0AD00AE0-0AE30AE6-0AF1",Gurmukhi:"0A01-0A030A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A3C0A3E-0A420A470A480A4B-0A4D0A510A59-0A5C0A5E0A66-0A75",Han:"2E80-2E992E9B-2EF32F00-2FD5300530073021-30293038-303B3400-4DB54E00-9FCCF900-FA6DFA70-FAD9",Hangul:"1100-11FF302E302F3131-318E3200-321E3260-327EA960-A97CAC00-D7A3D7B0-D7C6D7CB-D7FBFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",Hanunoo:"1720-1734",Hebrew:"0591-05C705D0-05EA05F0-05F4FB1D-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FB4F",Hiragana:"3041-3096309D-309F",Inherited:"0300-036F04850486064B-0655065F0670095109521CD0-1CD21CD4-1CE01CE2-1CE81CED1CF41DC0-1DE61DFC-1DFF200C200D20D0-20F0302A-302D3099309AFE00-FE0FFE20-FE26",Javanese:"A980-A9CDA9CF-A9D9A9DEA9DF",Kannada:"0C820C830C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBC-0CC40CC6-0CC80CCA-0CCD0CD50CD60CDE0CE0-0CE30CE6-0CEF0CF10CF2",Katakana:"30A1-30FA30FD-30FF31F0-31FF32D0-32FE3300-3357FF66-FF6FFF71-FF9D",Kayah_Li:"A900-A92F",Khmer:"1780-17DD17E0-17E917F0-17F919E0-19FF",Lao:"0E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB90EBB-0EBD0EC0-0EC40EC60EC8-0ECD0ED0-0ED90EDC-0EDF",Latin:"0041-005A0061-007A00AA00BA00C0-00D600D8-00F600F8-02B802E0-02E41D00-1D251D2C-1D5C1D62-1D651D6B-1D771D79-1DBE1E00-1EFF2071207F2090-209C212A212B2132214E2160-21882C60-2C7FA722-A787A78B-A78EA790-A793A7A0-A7AAA7F8-A7FFFB00-FB06FF21-FF3AFF41-FF5A",Lepcha:"1C00-1C371C3B-1C491C4D-1C4F",Limbu:"1900-191C1920-192B1930-193B19401944-194F",Lisu:"A4D0-A4FF",Malayalam:"0D020D030D05-0D0C0D0E-0D100D12-0D3A0D3D-0D440D46-0D480D4A-0D4E0D570D60-0D630D66-0D750D79-0D7F",Mandaic:"0840-085B085E",Meetei_Mayek:"AAE0-AAF6ABC0-ABEDABF0-ABF9",Mongolian:"1800180118041806-180E1810-18191820-18771880-18AA",Myanmar:"1000-109FAA60-AA7B",New_Tai_Lue:"1980-19AB19B0-19C919D0-19DA19DE19DF",Nko:"07C0-07FA",Ogham:"1680-169C",Ol_Chiki:"1C50-1C7F",Oriya:"0B01-0B030B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3C-0B440B470B480B4B-0B4D0B560B570B5C0B5D0B5F-0B630B66-0B77",Phags_Pa:"A840-A877",Rejang:"A930-A953A95F",Runic:"16A0-16EA16EE-16F0",Samaritan:"0800-082D0830-083E",Saurashtra:"A880-A8C4A8CE-A8D9",Sinhala:"0D820D830D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60DCA0DCF-0DD40DD60DD8-0DDF0DF2-0DF4",Sundanese:"1B80-1BBF1CC0-1CC7",Syloti_Nagri:"A800-A82B",Syriac:"0700-070D070F-074A074D-074F",Tagalog:"1700-170C170E-1714",Tagbanwa:"1760-176C176E-177017721773",Tai_Le:"1950-196D1970-1974",Tai_Tham:"1A20-1A5E1A60-1A7C1A7F-1A891A90-1A991AA0-1AAD",Tai_Viet:"AA80-AAC2AADB-AADF",Tamil:"0B820B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BBE-0BC20BC6-0BC80BCA-0BCD0BD00BD70BE6-0BFA",Telugu:"0C01-0C030C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D-0C440C46-0C480C4A-0C4D0C550C560C580C590C60-0C630C66-0C6F0C78-0C7F",Thaana:"0780-07B1",Thai:"0E01-0E3A0E40-0E5B",Tibetan:"0F00-0F470F49-0F6C0F71-0F970F99-0FBC0FBE-0FCC0FCE-0FD40FD90FDA",Tifinagh:"2D30-2D672D6F2D702D7F",Vai:"A500-A62B",Yi:"A000-A48CA490-A4C6"})})(XRegExp);
88//XRegExp Unicode Blocks 1.2.0
89(function(n){"use strict";if(!n.addUnicodePackage)throw new ReferenceError("Unicode Base must be loaded before Unicode Blocks");n.install("extensibility"),n.addUnicodePackage({InBasic_Latin:"0000-007F",InLatin_1_Supplement:"0080-00FF",InLatin_Extended_A:"0100-017F",InLatin_Extended_B:"0180-024F",InIPA_Extensions:"0250-02AF",InSpacing_Modifier_Letters:"02B0-02FF",InCombining_Diacritical_Marks:"0300-036F",InGreek_and_Coptic:"0370-03FF",InCyrillic:"0400-04FF",InCyrillic_Supplement:"0500-052F",InArmenian:"0530-058F",InHebrew:"0590-05FF",InArabic:"0600-06FF",InSyriac:"0700-074F",InArabic_Supplement:"0750-077F",InThaana:"0780-07BF",InNKo:"07C0-07FF",InSamaritan:"0800-083F",InMandaic:"0840-085F",InArabic_Extended_A:"08A0-08FF",InDevanagari:"0900-097F",InBengali:"0980-09FF",InGurmukhi:"0A00-0A7F",InGujarati:"0A80-0AFF",InOriya:"0B00-0B7F",InTamil:"0B80-0BFF",InTelugu:"0C00-0C7F",InKannada:"0C80-0CFF",InMalayalam:"0D00-0D7F",InSinhala:"0D80-0DFF",InThai:"0E00-0E7F",InLao:"0E80-0EFF",InTibetan:"0F00-0FFF",InMyanmar:"1000-109F",InGeorgian:"10A0-10FF",InHangul_Jamo:"1100-11FF",InEthiopic:"1200-137F",InEthiopic_Supplement:"1380-139F",InCherokee:"13A0-13FF",InUnified_Canadian_Aboriginal_Syllabics:"1400-167F",InOgham:"1680-169F",InRunic:"16A0-16FF",InTagalog:"1700-171F",InHanunoo:"1720-173F",InBuhid:"1740-175F",InTagbanwa:"1760-177F",InKhmer:"1780-17FF",InMongolian:"1800-18AF",InUnified_Canadian_Aboriginal_Syllabics_Extended:"18B0-18FF",InLimbu:"1900-194F",InTai_Le:"1950-197F",InNew_Tai_Lue:"1980-19DF",InKhmer_Symbols:"19E0-19FF",InBuginese:"1A00-1A1F",InTai_Tham:"1A20-1AAF",InBalinese:"1B00-1B7F",InSundanese:"1B80-1BBF",InBatak:"1BC0-1BFF",InLepcha:"1C00-1C4F",InOl_Chiki:"1C50-1C7F",InSundanese_Supplement:"1CC0-1CCF",InVedic_Extensions:"1CD0-1CFF",InPhonetic_Extensions:"1D00-1D7F",InPhonetic_Extensions_Supplement:"1D80-1DBF",InCombining_Diacritical_Marks_Supplement:"1DC0-1DFF",InLatin_Extended_Additional:"1E00-1EFF",InGreek_Extended:"1F00-1FFF",InGeneral_Punctuation:"2000-206F",InSuperscripts_and_Subscripts:"2070-209F",InCurrency_Symbols:"20A0-20CF",InCombining_Diacritical_Marks_for_Symbols:"20D0-20FF",InLetterlike_Symbols:"2100-214F",InNumber_Forms:"2150-218F",InArrows:"2190-21FF",InMathematical_Operators:"2200-22FF",InMiscellaneous_Technical:"2300-23FF",InControl_Pictures:"2400-243F",InOptical_Character_Recognition:"2440-245F",InEnclosed_Alphanumerics:"2460-24FF",InBox_Drawing:"2500-257F",InBlock_Elements:"2580-259F",InGeometric_Shapes:"25A0-25FF",InMiscellaneous_Symbols:"2600-26FF",InDingbats:"2700-27BF",InMiscellaneous_Mathematical_Symbols_A:"27C0-27EF",InSupplemental_Arrows_A:"27F0-27FF",InBraille_Patterns:"2800-28FF",InSupplemental_Arrows_B:"2900-297F",InMiscellaneous_Mathematical_Symbols_B:"2980-29FF",InSupplemental_Mathematical_Operators:"2A00-2AFF",InMiscellaneous_Symbols_and_Arrows:"2B00-2BFF",InGlagolitic:"2C00-2C5F",InLatin_Extended_C:"2C60-2C7F",InCoptic:"2C80-2CFF",InGeorgian_Supplement:"2D00-2D2F",InTifinagh:"2D30-2D7F",InEthiopic_Extended:"2D80-2DDF",InCyrillic_Extended_A:"2DE0-2DFF",InSupplemental_Punctuation:"2E00-2E7F",InCJK_Radicals_Supplement:"2E80-2EFF",InKangxi_Radicals:"2F00-2FDF",InIdeographic_Description_Characters:"2FF0-2FFF",InCJK_Symbols_and_Punctuation:"3000-303F",InHiragana:"3040-309F",InKatakana:"30A0-30FF",InBopomofo:"3100-312F",InHangul_Compatibility_Jamo:"3130-318F",InKanbun:"3190-319F",InBopomofo_Extended:"31A0-31BF",InCJK_Strokes:"31C0-31EF",InKatakana_Phonetic_Extensions:"31F0-31FF",InEnclosed_CJK_Letters_and_Months:"3200-32FF",InCJK_Compatibility:"3300-33FF",InCJK_Unified_Ideographs_Extension_A:"3400-4DBF",InYijing_Hexagram_Symbols:"4DC0-4DFF",InCJK_Unified_Ideographs:"4E00-9FFF",InYi_Syllables:"A000-A48F",InYi_Radicals:"A490-A4CF",InLisu:"A4D0-A4FF",InVai:"A500-A63F",InCyrillic_Extended_B:"A640-A69F",InBamum:"A6A0-A6FF",InModifier_Tone_Letters:"A700-A71F",InLatin_Extended_D:"A720-A7FF",InSyloti_Nagri:"A800-A82F",InCommon_Indic_Number_Forms:"A830-A83F",InPhags_pa:"A840-A87F",InSaurashtra:"A880-A8DF",InDevanagari_Extended:"A8E0-A8FF",InKayah_Li:"A900-A92F",InRejang:"A930-A95F",InHangul_Jamo_Extended_A:"A960-A97F",InJavanese:"A980-A9DF",InCham:"AA00-AA5F",InMyanmar_Extended_A:"AA60-AA7F",InTai_Viet:"AA80-AADF",InMeetei_Mayek_Extensions:"AAE0-AAFF",InEthiopic_Extended_A:"AB00-AB2F",InMeetei_Mayek:"ABC0-ABFF",InHangul_Syllables:"AC00-D7AF",InHangul_Jamo_Extended_B:"D7B0-D7FF",InHigh_Surrogates:"D800-DB7F",InHigh_Private_Use_Surrogates:"DB80-DBFF",InLow_Surrogates:"DC00-DFFF",InPrivate_Use_Area:"E000-F8FF",InCJK_Compatibility_Ideographs:"F900-FAFF",InAlphabetic_Presentation_Forms:"FB00-FB4F",InArabic_Presentation_Forms_A:"FB50-FDFF",InVariation_Selectors:"FE00-FE0F",InVertical_Forms:"FE10-FE1F",InCombining_Half_Marks:"FE20-FE2F",InCJK_Compatibility_Forms:"FE30-FE4F",InSmall_Form_Variants:"FE50-FE6F",InArabic_Presentation_Forms_B:"FE70-FEFF",InHalfwidth_and_Fullwidth_Forms:"FF00-FFEF",InSpecials:"FFF0-FFFF"})})(XRegExp);
90//XRegExp Unicode Properties 1.0.0
91(function(n){"use strict";if(!n.addUnicodePackage)throw new ReferenceError("Unicode Base must be loaded before Unicode Properties");n.install("extensibility"),n.addUnicodePackage({Alphabetic:"0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE03450370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05270531-055605590561-058705B0-05BD05BF05C105C205C405C505C705D0-05EA05F0-05F20610-061A0620-06570659-065F066E-06D306D5-06DC06E1-06E806ED-06EF06FA-06FC06FF0710-073F074D-07B107CA-07EA07F407F507FA0800-0817081A-082C0840-085808A008A2-08AC08E4-08E908F0-08FE0900-093B093D-094C094E-09500955-09630971-09770979-097F0981-09830985-098C098F09900993-09A809AA-09B009B209B6-09B909BD-09C409C709C809CB09CC09CE09D709DC09DD09DF-09E309F009F10A01-0A030A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A3E-0A420A470A480A4B0A4C0A510A59-0A5C0A5E0A70-0A750A81-0A830A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD-0AC50AC7-0AC90ACB0ACC0AD00AE0-0AE30B01-0B030B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D-0B440B470B480B4B0B4C0B560B570B5C0B5D0B5F-0B630B710B820B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BBE-0BC20BC6-0BC80BCA-0BCC0BD00BD70C01-0C030C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D-0C440C46-0C480C4A-0C4C0C550C560C580C590C60-0C630C820C830C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD-0CC40CC6-0CC80CCA-0CCC0CD50CD60CDE0CE0-0CE30CF10CF20D020D030D05-0D0C0D0E-0D100D12-0D3A0D3D-0D440D46-0D480D4A-0D4C0D4E0D570D60-0D630D7A-0D7F0D820D830D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60DCF-0DD40DD60DD8-0DDF0DF20DF30E01-0E3A0E40-0E460E4D0E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB90EBB-0EBD0EC0-0EC40EC60ECD0EDC-0EDF0F000F40-0F470F49-0F6C0F71-0F810F88-0F970F99-0FBC1000-10361038103B-103F1050-10621065-1068106E-1086108E109C109D10A0-10C510C710CD10D0-10FA10FC-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A135F1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA16EE-16F01700-170C170E-17131720-17331740-17531760-176C176E-1770177217731780-17B317B6-17C817D717DC1820-18771880-18AA18B0-18F51900-191C1920-192B1930-19381950-196D1970-19741980-19AB19B0-19C91A00-1A1B1A20-1A5E1A61-1A741AA71B00-1B331B35-1B431B45-1B4B1B80-1BA91BAC-1BAF1BBA-1BE51BE7-1BF11C00-1C351C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF31CF51CF61D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209C21022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E2160-218824B6-24E92C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2CF22CF32D00-2D252D272D2D2D30-2D672D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2DE0-2DFF2E2F3005-30073021-30293031-30353038-303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31BA31F0-31FF3400-4DB54E00-9FCCA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A66EA674-A67BA67F-A697A69F-A6EFA717-A71FA722-A788A78B-A78EA790-A793A7A0-A7AAA7F8-A801A803-A805A807-A80AA80C-A827A840-A873A880-A8C3A8F2-A8F7A8FBA90A-A92AA930-A952A960-A97CA980-A9B2A9B4-A9BFA9CFAA00-AA36AA40-AA4DAA60-AA76AA7AAA80-AABEAAC0AAC2AADB-AADDAAE0-AAEFAAF2-AAF5AB01-AB06AB09-AB0EAB11-AB16AB20-AB26AB28-AB2EABC0-ABEAAC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1D-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",Uppercase:"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E05200522052405260531-055610A0-10C510C710CD1E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F21452160-216F218324B6-24CF2C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CED2CF2A640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA660A662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BA78DA790A792A7A0A7A2A7A4A7A6A7A8A7AAFF21-FF3A",Lowercase:"0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02B802C002C102E0-02E40345037103730377037A-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F05210523052505270561-05871D00-1DBF1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF72071207F2090-209C210A210E210F2113212F21342139213C213D2146-2149214E2170-217F218424D0-24E92C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7D2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2CF32D00-2D252D272D2DA641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA661A663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76F-A778A77AA77CA77FA781A783A785A787A78CA78EA791A793A7A1A7A3A7A5A7A7A7A9A7F8-A7FAFB00-FB06FB13-FB17FF41-FF5A",White_Space:"0009-000D0020008500A01680180E2000-200A20282029202F205F3000",Noncharacter_Code_Point:"FDD0-FDEFFFFEFFFF",Default_Ignorable_Code_Point:"00AD034F115F116017B417B5180B-180D200B-200F202A-202E2060-206F3164FE00-FE0FFEFFFFA0FFF0-FFF8",Any:"0000-FFFF",Ascii:"0000-007F",Assigned:"0000-0377037A-037E0384-038A038C038E-03A103A3-05270531-05560559-055F0561-05870589058A058F0591-05C705D0-05EA05F0-05F40600-06040606-061B061E-070D070F-074A074D-07B107C0-07FA0800-082D0830-083E0840-085B085E08A008A2-08AC08E4-08FE0900-09770979-097F0981-09830985-098C098F09900993-09A809AA-09B009B209B6-09B909BC-09C409C709C809CB-09CE09D709DC09DD09DF-09E309E6-09FB0A01-0A030A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A3C0A3E-0A420A470A480A4B-0A4D0A510A59-0A5C0A5E0A66-0A750A81-0A830A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABC-0AC50AC7-0AC90ACB-0ACD0AD00AE0-0AE30AE6-0AF10B01-0B030B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3C-0B440B470B480B4B-0B4D0B560B570B5C0B5D0B5F-0B630B66-0B770B820B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BBE-0BC20BC6-0BC80BCA-0BCD0BD00BD70BE6-0BFA0C01-0C030C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D-0C440C46-0C480C4A-0C4D0C550C560C580C590C60-0C630C66-0C6F0C78-0C7F0C820C830C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBC-0CC40CC6-0CC80CCA-0CCD0CD50CD60CDE0CE0-0CE30CE6-0CEF0CF10CF20D020D030D05-0D0C0D0E-0D100D12-0D3A0D3D-0D440D46-0D480D4A-0D4E0D570D60-0D630D66-0D750D79-0D7F0D820D830D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60DCA0DCF-0DD40DD60DD8-0DDF0DF2-0DF40E01-0E3A0E3F-0E5B0E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB90EBB-0EBD0EC0-0EC40EC60EC8-0ECD0ED0-0ED90EDC-0EDF0F00-0F470F49-0F6C0F71-0F970F99-0FBC0FBE-0FCC0FCE-0FDA1000-10C510C710CD10D0-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A135D-137C1380-139913A0-13F41400-169C16A0-16F01700-170C170E-17141720-17361740-17531760-176C176E-1770177217731780-17DD17E0-17E917F0-17F91800-180E1810-18191820-18771880-18AA18B0-18F51900-191C1920-192B1930-193B19401944-196D1970-19741980-19AB19B0-19C919D0-19DA19DE-1A1B1A1E-1A5E1A60-1A7C1A7F-1A891A90-1A991AA0-1AAD1B00-1B4B1B50-1B7C1B80-1BF31BFC-1C371C3B-1C491C4D-1C7F1CC0-1CC71CD0-1CF61D00-1DE61DFC-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FC41FC6-1FD31FD6-1FDB1FDD-1FEF1FF2-1FF41FF6-1FFE2000-2064206A-20712074-208E2090-209C20A0-20B920D0-20F02100-21892190-23F32400-24262440-244A2460-26FF2701-2B4C2B50-2B592C00-2C2E2C30-2C5E2C60-2CF32CF9-2D252D272D2D2D30-2D672D6F2D702D7F-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2DE0-2E3B2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB3000-303F3041-30963099-30FF3105-312D3131-318E3190-31BA31C0-31E331F0-321E3220-32FE3300-4DB54DC0-9FCCA000-A48CA490-A4C6A4D0-A62BA640-A697A69F-A6F7A700-A78EA790-A793A7A0-A7AAA7F8-A82BA830-A839A840-A877A880-A8C4A8CE-A8D9A8E0-A8FBA900-A953A95F-A97CA980-A9CDA9CF-A9D9A9DEA9DFAA00-AA36AA40-AA4DAA50-AA59AA5C-AA7BAA80-AAC2AADB-AAF6AB01-AB06AB09-AB0EAB11-AB16AB20-AB26AB28-AB2EABC0-ABEDABF0-ABF9AC00-D7A3D7B0-D7C6D7CB-D7FBD800-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1D-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBC1FBD3-FD3FFD50-FD8FFD92-FDC7FDF0-FDFDFE00-FE19FE20-FE26FE30-FE52FE54-FE66FE68-FE6BFE70-FE74FE76-FEFCFEFFFF01-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDCFFE0-FFE6FFE8-FFEEFFF9-FFFD"})})(XRegExp);
92//XRegExp.matchRecursive 0.2.0
93(function(n){"use strict";function t(n,t,i,r){return{value:n,name:t,start:i,end:r}}n.matchRecursive=function(i,r,u,f,e){f=f||"",e=e||{};var g=f.indexOf("g")>-1,nt=f.indexOf("y")>-1,d=f.replace(/y/g,""),y=e.escapeChar,o=e.valueNames,v=[],b=0,h=0,s=0,c=0,p,w,l,a,k;if(r=n(r,d),u=n(u,d),y){if(y.length>1)throw new SyntaxError("can't use more than one escape character");y=n.escape(y),k=new RegExp("(?:"+y+"[\\S\\s]|(?:(?!"+n.union([r,u]).source+")[^"+y+"])+)+",f.replace(/[^im]+/g,""))}for(;;){if(y&&(s+=(n.exec(i,k,s,"sticky")||[""])[0].length),l=n.exec(i,r,s),a=n.exec(i,u,s),l&&a&&(l.index<=a.index?a=null:l=null),l||a)h=(l||a).index,s=h+(l||a)[0].length;else if(!b)break;if(nt&&!b&&h>c)break;if(l)b||(p=h,w=s),++b;else if(a&&b){if(!--b&&(o?(o[0]&&p>c&&v.push(t(o[0],i.slice(c,p),c,p)),o[1]&&v.push(t(o[1],i.slice(p,w),p,w)),o[2]&&v.push(t(o[2],i.slice(w,h),w,h)),o[3]&&v.push(t(o[3],i.slice(h,s),h,s))):v.push(i.slice(w,h)),c=s,!g))break}else throw new Error("string contains unbalanced delimiters");h===s&&++s}return g&&!nt&&o&&o[0]&&i.length>c&&v.push(t(o[0],i.slice(c),c,i.length)),v}})(XRegExp);
94//XRegExp.build 0.1.0
95(function(n){"use strict";function u(n){var i=/^(?:\(\?:\))?\^/,t=/\$(?:\(\?:\))?$/;return t.test(n.replace(/\\[\s\S]/g,""))?n.replace(i,"").replace(t,""):n}function t(t){return n.isRegExp(t)?t.xregexp&&!t.xregexp.isNative?t:n(t.source):n(t)}var i=/(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g,r=n.union([/\({{([\w$]+)}}\)|{{([\w$]+)}}/,i],"g");n.build=function(f,e,o){var w=/^\(\?([\w$]+)\)/.exec(f),l={},s=0,v,h=0,p=[0],y,a,c;w&&(o=o||"",w[1].replace(/./g,function(n){o+=o.indexOf(n)>-1?"":n}));for(c in e)e.hasOwnProperty(c)&&(a=t(e[c]),l[c]={pattern:u(a.source),names:a.xregexp.captureNames||[]});return f=t(f),y=f.xregexp.captureNames||[],f=f.source.replace(r,function(n,t,r,u,f){var o=t||r,e,c;if(o){if(!l.hasOwnProperty(o))throw new ReferenceError("undefined property "+n);return t?(e=y[h],p[++h]=++s,c="(?<"+(e||o)+">"):c="(?:",v=s,c+l[o].pattern.replace(i,function(n,t,i){if(t){if(e=l[o].names[s-v],++s,e)return"(?<"+e+">"}else if(i)return"\\"+(+i+v);return n})+")"}if(u){if(e=y[h],p[++h]=++s,e)return"(?<"+e+">"}else if(f)return"\\"+p[+f];return n}),n(f,o)}})(XRegExp);
96//XRegExp Prototype Methods 1.0.0
97(function(n){"use strict";function t(n,t){for(var i in t)t.hasOwnProperty(i)&&(n[i]=t[i])}t(n.prototype,{apply:function(n,t){return this.test(t[0])},call:function(n,t){return this.test(t)},forEach:function(t,i,r){return n.forEach(t,this,i,r)},globalize:function(){return n.globalize(this)},xexec:function(t,i,r){return n.exec(t,this,i,r)},xtest:function(t,i,r){return n.test(t,this,i,r)}})})(XRegExp);/*!
98 * jQuery JavaScript Library v1.11.1
99 * http://jquery.com/
100 *
101 * Includes Sizzle.js
102 * http://sizzlejs.com/
103 *
104 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
105 * Released under the MIT license
106 * http://jquery.org/license
107 *
108 * Date: 2014-05-01T17:42Z
109 */
110
111(function( global, factory ) {
112
113 if ( typeof module === "object" && typeof module.exports === "object" ) {
114 // For CommonJS and CommonJS-like environments where a proper window is present,
115 // execute the factory and get jQuery
116 // For environments that do not inherently posses a window with a document
117 // (such as Node.js), expose a jQuery-making factory as module.exports
118 // This accentuates the need for the creation of a real window
119 // e.g. var jQuery = require("jquery")(window);
120 // See ticket #14549 for more info
121 module.exports = global.document ?
122 factory( global, true ) :
123 function( w ) {
124 if ( !w.document ) {
125 throw new Error( "jQuery requires a window with a document" );
126 }
127 return factory( w );
128 };
129 } else {
130 factory( global );
131 }
132
133// Pass this if window is not defined yet
134}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
135
136// Can't do this because several apps including ASP.NET trace
137// the stack via arguments.caller.callee and Firefox dies if
138// you try to trace through "use strict" call chains. (#13335)
139// Support: Firefox 18+
140//
141
142var deletedIds = [];
143
144var slice = deletedIds.slice;
145
146var concat = deletedIds.concat;
147
148var push = deletedIds.push;
149
150var indexOf = deletedIds.indexOf;
151
152var class2type = {};
153
154var toString = class2type.toString;
155
156var hasOwn = class2type.hasOwnProperty;
157
158var support = {};
159
160
161
162var
163 version = "1.11.1",
164
165 // Define a local copy of jQuery
166 jQuery = function( selector, context ) {
167 // The jQuery object is actually just the init constructor 'enhanced'
168 // Need init if jQuery is called (just allow error to be thrown if not included)
169 return new jQuery.fn.init( selector, context );
170 },
171
172 // Support: Android<4.1, IE<9
173 // Make sure we trim BOM and NBSP
174 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
175
176 // Matches dashed string for camelizing
177 rmsPrefix = /^-ms-/,
178 rdashAlpha = /-([\da-z])/gi,
179
180 // Used by jQuery.camelCase as callback to replace()
181 fcamelCase = function( all, letter ) {
182 return letter.toUpperCase();
183 };
184
185jQuery.fn = jQuery.prototype = {
186 // The current version of jQuery being used
187 jquery: version,
188
189 constructor: jQuery,
190
191 // Start with an empty selector
192 selector: "",
193
194 // The default length of a jQuery object is 0
195 length: 0,
196
197 toArray: function() {
198 return slice.call( this );
199 },
200
201 // Get the Nth element in the matched element set OR
202 // Get the whole matched element set as a clean array
203 get: function( num ) {
204 return num != null ?
205
206 // Return just the one element from the set
207 ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
208
209 // Return all the elements in a clean array
210 slice.call( this );
211 },
212
213 // Take an array of elements and push it onto the stack
214 // (returning the new matched element set)
215 pushStack: function( elems ) {
216
217 // Build a new jQuery matched element set
218 var ret = jQuery.merge( this.constructor(), elems );
219
220 // Add the old object onto the stack (as a reference)
221 ret.prevObject = this;
222 ret.context = this.context;
223
224 // Return the newly-formed element set
225 return ret;
226 },
227
228 // Execute a callback for every element in the matched set.
229 // (You can seed the arguments with an array of args, but this is
230 // only used internally.)
231 each: function( callback, args ) {
232 return jQuery.each( this, callback, args );
233 },
234
235 map: function( callback ) {
236 return this.pushStack( jQuery.map(this, function( elem, i ) {
237 return callback.call( elem, i, elem );
238 }));
239 },
240
241 slice: function() {
242 return this.pushStack( slice.apply( this, arguments ) );
243 },
244
245 first: function() {
246 return this.eq( 0 );
247 },
248
249 last: function() {
250 return this.eq( -1 );
251 },
252
253 eq: function( i ) {
254 var len = this.length,
255 j = +i + ( i < 0 ? len : 0 );
256 return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
257 },
258
259 end: function() {
260 return this.prevObject || this.constructor(null);
261 },
262
263 // For internal use only.
264 // Behaves like an Array's method, not like a jQuery method.
265 push: push,
266 sort: deletedIds.sort,
267 splice: deletedIds.splice
268};
269
270jQuery.extend = jQuery.fn.extend = function() {
271 var src, copyIsArray, copy, name, options, clone,
272 target = arguments[0] || {},
273 i = 1,
274 length = arguments.length,
275 deep = false;
276
277 // Handle a deep copy situation
278 if ( typeof target === "boolean" ) {
279 deep = target;
280
281 // skip the boolean and the target
282 target = arguments[ i ] || {};
283 i++;
284 }
285
286 // Handle case when target is a string or something (possible in deep copy)
287 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
288 target = {};
289 }
290
291 // extend jQuery itself if only one argument is passed
292 if ( i === length ) {
293 target = this;
294 i--;
295 }
296
297 for ( ; i < length; i++ ) {
298 // Only deal with non-null/undefined values
299 if ( (options = arguments[ i ]) != null ) {
300 // Extend the base object
301 for ( name in options ) {
302 src = target[ name ];
303 copy = options[ name ];
304
305 // Prevent never-ending loop
306 if ( target === copy ) {
307 continue;
308 }
309
310 // Recurse if we're merging plain objects or arrays
311 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
312 if ( copyIsArray ) {
313 copyIsArray = false;
314 clone = src && jQuery.isArray(src) ? src : [];
315
316 } else {
317 clone = src && jQuery.isPlainObject(src) ? src : {};
318 }
319
320 // Never move original objects, clone them
321 target[ name ] = jQuery.extend( deep, clone, copy );
322
323 // Don't bring in undefined values
324 } else if ( copy !== undefined ) {
325 target[ name ] = copy;
326 }
327 }
328 }
329 }
330
331 // Return the modified object
332 return target;
333};
334
335jQuery.extend({
336 // Unique for each copy of jQuery on the page
337 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
338
339 // Assume jQuery is ready without the ready module
340 isReady: true,
341
342 error: function( msg ) {
343 throw new Error( msg );
344 },
345
346 noop: function() {},
347
348 // See test/unit/core.js for details concerning isFunction.
349 // Since version 1.3, DOM methods and functions like alert
350 // aren't supported. They return false on IE (#2968).
351 isFunction: function( obj ) {
352 return jQuery.type(obj) === "function";
353 },
354
355 isArray: Array.isArray || function( obj ) {
356 return jQuery.type(obj) === "array";
357 },
358
359 isWindow: function( obj ) {
360 /* jshint eqeqeq: false */
361 return obj != null && obj == obj.window;
362 },
363
364 isNumeric: function( obj ) {
365 // parseFloat NaNs numeric-cast false positives (null|true|false|"")
366 // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
367 // subtraction forces infinities to NaN
368 return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0;
369 },
370
371 isEmptyObject: function( obj ) {
372 var name;
373 for ( name in obj ) {
374 return false;
375 }
376 return true;
377 },
378
379 isPlainObject: function( obj ) {
380 var key;
381
382 // Must be an Object.
383 // Because of IE, we also have to check the presence of the constructor property.
384 // Make sure that DOM nodes and window objects don't pass through, as well
385 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
386 return false;
387 }
388
389 try {
390 // Not own constructor property must be Object
391 if ( obj.constructor &&
392 !hasOwn.call(obj, "constructor") &&
393 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
394 return false;
395 }
396 } catch ( e ) {
397 // IE8,9 Will throw exceptions on certain host objects #9897
398 return false;
399 }
400
401 // Support: IE<9
402 // Handle iteration over inherited properties before own properties.
403 if ( support.ownLast ) {
404 for ( key in obj ) {
405 return hasOwn.call( obj, key );
406 }
407 }
408
409 // Own properties are enumerated firstly, so to speed up,
410 // if last one is own, then all properties are own.
411 for ( key in obj ) {}
412
413 return key === undefined || hasOwn.call( obj, key );
414 },
415
416 type: function( obj ) {
417 if ( obj == null ) {
418 return obj + "";
419 }
420 return typeof obj === "object" || typeof obj === "function" ?
421 class2type[ toString.call(obj) ] || "object" :
422 typeof obj;
423 },
424
425 // Evaluates a script in a global context
426 // Workarounds based on findings by Jim Driscoll
427 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
428 globalEval: function( data ) {
429 if ( data && jQuery.trim( data ) ) {
430 // We use execScript on Internet Explorer
431 // We use an anonymous function so that context is window
432 // rather than jQuery in Firefox
433 ( window.execScript || function( data ) {
434 window[ "eval" ].call( window, data );
435 } )( data );
436 }
437 },
438
439 // Convert dashed to camelCase; used by the css and data modules
440 // Microsoft forgot to hump their vendor prefix (#9572)
441 camelCase: function( string ) {
442 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
443 },
444
445 nodeName: function( elem, name ) {
446 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
447 },
448
449 // args is for internal usage only
450 each: function( obj, callback, args ) {
451 var value,
452 i = 0,
453 length = obj.length,
454 isArray = isArraylike( obj );
455
456 if ( args ) {
457 if ( isArray ) {
458 for ( ; i < length; i++ ) {
459 value = callback.apply( obj[ i ], args );
460
461 if ( value === false ) {
462 break;
463 }
464 }
465 } else {
466 for ( i in obj ) {
467 value = callback.apply( obj[ i ], args );
468
469 if ( value === false ) {
470 break;
471 }
472 }
473 }
474
475 // A special, fast, case for the most common use of each
476 } else {
477 if ( isArray ) {
478 for ( ; i < length; i++ ) {
479 value = callback.call( obj[ i ], i, obj[ i ] );
480
481 if ( value === false ) {
482 break;
483 }
484 }
485 } else {
486 for ( i in obj ) {
487 value = callback.call( obj[ i ], i, obj[ i ] );
488
489 if ( value === false ) {
490 break;
491 }
492 }
493 }
494 }
495
496 return obj;
497 },
498
499 // Support: Android<4.1, IE<9
500 trim: function( text ) {
501 return text == null ?
502 "" :
503 ( text + "" ).replace( rtrim, "" );
504 },
505
506 // results is for internal usage only
507 makeArray: function( arr, results ) {
508 var ret = results || [];
509
510 if ( arr != null ) {
511 if ( isArraylike( Object(arr) ) ) {
512 jQuery.merge( ret,
513 typeof arr === "string" ?
514 [ arr ] : arr
515 );
516 } else {
517 push.call( ret, arr );
518 }
519 }
520
521 return ret;
522 },
523
524 inArray: function( elem, arr, i ) {
525 var len;
526
527 if ( arr ) {
528 if ( indexOf ) {
529 return indexOf.call( arr, elem, i );
530 }
531
532 len = arr.length;
533 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
534
535 for ( ; i < len; i++ ) {
536 // Skip accessing in sparse arrays
537 if ( i in arr && arr[ i ] === elem ) {
538 return i;
539 }
540 }
541 }
542
543 return -1;
544 },
545
546 merge: function( first, second ) {
547 var len = +second.length,
548 j = 0,
549 i = first.length;
550
551 while ( j < len ) {
552 first[ i++ ] = second[ j++ ];
553 }
554
555 // Support: IE<9
556 // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
557 if ( len !== len ) {
558 while ( second[j] !== undefined ) {
559 first[ i++ ] = second[ j++ ];
560 }
561 }
562
563 first.length = i;
564
565 return first;
566 },
567
568 grep: function( elems, callback, invert ) {
569 var callbackInverse,
570 matches = [],
571 i = 0,
572 length = elems.length,
573 callbackExpect = !invert;
574
575 // Go through the array, only saving the items
576 // that pass the validator function
577 for ( ; i < length; i++ ) {
578 callbackInverse = !callback( elems[ i ], i );
579 if ( callbackInverse !== callbackExpect ) {
580 matches.push( elems[ i ] );
581 }
582 }
583
584 return matches;
585 },
586
587 // arg is for internal usage only
588 map: function( elems, callback, arg ) {
589 var value,
590 i = 0,
591 length = elems.length,
592 isArray = isArraylike( elems ),
593 ret = [];
594
595 // Go through the array, translating each of the items to their new values
596 if ( isArray ) {
597 for ( ; i < length; i++ ) {
598 value = callback( elems[ i ], i, arg );
599
600 if ( value != null ) {
601 ret.push( value );
602 }
603 }
604
605 // Go through every key on the object,
606 } else {
607 for ( i in elems ) {
608 value = callback( elems[ i ], i, arg );
609
610 if ( value != null ) {
611 ret.push( value );
612 }
613 }
614 }
615
616 // Flatten any nested arrays
617 return concat.apply( [], ret );
618 },
619
620 // A global GUID counter for objects
621 guid: 1,
622
623 // Bind a function to a context, optionally partially applying any
624 // arguments.
625 proxy: function( fn, context ) {
626 var args, proxy, tmp;
627
628 if ( typeof context === "string" ) {
629 tmp = fn[ context ];
630 context = fn;
631 fn = tmp;
632 }
633
634 // Quick check to determine if target is callable, in the spec
635 // this throws a TypeError, but we will just return undefined.
636 if ( !jQuery.isFunction( fn ) ) {
637 return undefined;
638 }
639
640 // Simulated bind
641 args = slice.call( arguments, 2 );
642 proxy = function() {
643 return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
644 };
645
646 // Set the guid of unique handler to the same of original handler, so it can be removed
647 proxy.guid = fn.guid = fn.guid || jQuery.guid++;
648
649 return proxy;
650 },
651
652 now: function() {
653 return +( new Date() );
654 },
655
656 // jQuery.support is not used in Core but other projects attach their
657 // properties to it so it needs to exist.
658 support: support
659});
660
661// Populate the class2type map
662jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
663 class2type[ "[object " + name + "]" ] = name.toLowerCase();
664});
665
666function isArraylike( obj ) {
667 var length = obj.length,
668 type = jQuery.type( obj );
669
670 if ( type === "function" || jQuery.isWindow( obj ) ) {
671 return false;
672 }
673
674 if ( obj.nodeType === 1 && length ) {
675 return true;
676 }
677
678 return type === "array" || length === 0 ||
679 typeof length === "number" && length > 0 && ( length - 1 ) in obj;
680}
681var Sizzle =
682/*!
683 * Sizzle CSS Selector Engine v1.10.19
684 * http://sizzlejs.com/
685 *
686 * Copyright 2013 jQuery Foundation, Inc. and other contributors
687 * Released under the MIT license
688 * http://jquery.org/license
689 *
690 * Date: 2014-04-18
691 */
692(function( window ) {
693
694var i,
695 support,
696 Expr,
697 getText,
698 isXML,
699 tokenize,
700 compile,
701 select,
702 outermostContext,
703 sortInput,
704 hasDuplicate,
705
706 // Local document vars
707 setDocument,
708 document,
709 docElem,
710 documentIsHTML,
711 rbuggyQSA,
712 rbuggyMatches,
713 matches,
714 contains,
715
716 // Instance-specific data
717 expando = "sizzle" + -(new Date()),
718 preferredDoc = window.document,
719 dirruns = 0,
720 done = 0,
721 classCache = createCache(),
722 tokenCache = createCache(),
723 compilerCache = createCache(),
724 sortOrder = function( a, b ) {
725 if ( a === b ) {
726 hasDuplicate = true;
727 }
728 return 0;
729 },
730
731 // General-purpose constants
732 strundefined = typeof undefined,
733 MAX_NEGATIVE = 1 << 31,
734
735 // Instance methods
736 hasOwn = ({}).hasOwnProperty,
737 arr = [],
738 pop = arr.pop,
739 push_native = arr.push,
740 push = arr.push,
741 slice = arr.slice,
742 // Use a stripped-down indexOf if we can't use a native one
743 indexOf = arr.indexOf || function( elem ) {
744 var i = 0,
745 len = this.length;
746 for ( ; i < len; i++ ) {
747 if ( this[i] === elem ) {
748 return i;
749 }
750 }
751 return -1;
752 },
753
754 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
755
756 // Regular expressions
757
758 // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
759 whitespace = "[\\x20\\t\\r\\n\\f]",
760 // http://www.w3.org/TR/css3-syntax/#characters
761 characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
762
763 // Loosely modeled on CSS identifier characters
764 // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
765 // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
766 identifier = characterEncoding.replace( "w", "w#" ),
767
768 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
769 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
770 // Operator (capture 2)
771 "*([*^$|!~]?=)" + whitespace +
772 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
773 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
774 "*\\]",
775
776 pseudos = ":(" + characterEncoding + ")(?:\\((" +
777 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
778 // 1. quoted (capture 3; capture 4 or capture 5)
779 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
780 // 2. simple (capture 6)
781 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
782 // 3. anything else (capture 2)
783 ".*" +
784 ")\\)|)",
785
786 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
787 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
788
789 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
790 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
791
792 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
793
794 rpseudo = new RegExp( pseudos ),
795 ridentifier = new RegExp( "^" + identifier + "$" ),
796
797 matchExpr = {
798 "ID": new RegExp( "^#(" + characterEncoding + ")" ),
799 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
800 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
801 "ATTR": new RegExp( "^" + attributes ),
802 "PSEUDO": new RegExp( "^" + pseudos ),
803 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
804 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
805 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
806 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
807 // For use in libraries implementing .is()
808 // We use this for POS matching in `select`
809 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
810 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
811 },
812
813 rinputs = /^(?:input|select|textarea|button)$/i,
814 rheader = /^h\d$/i,
815
816 rnative = /^[^{]+\{\s*\[native \w/,
817
818 // Easily-parseable/retrievable ID or TAG or CLASS selectors
819 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
820
821 rsibling = /[+~]/,
822 rescape = /'|\\/g,
823
824 // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
825 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
826 funescape = function( _, escaped, escapedWhitespace ) {
827 var high = "0x" + escaped - 0x10000;
828 // NaN means non-codepoint
829 // Support: Firefox<24
830 // Workaround erroneous numeric interpretation of +"0x"
831 return high !== high || escapedWhitespace ?
832 escaped :
833 high < 0 ?
834 // BMP codepoint
835 String.fromCharCode( high + 0x10000 ) :
836 // Supplemental Plane codepoint (surrogate pair)
837 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
838 };
839
840// Optimize for push.apply( _, NodeList )
841try {
842 push.apply(
843 (arr = slice.call( preferredDoc.childNodes )),
844 preferredDoc.childNodes
845 );
846 // Support: Android<4.0
847 // Detect silently failing push.apply
848 arr[ preferredDoc.childNodes.length ].nodeType;
849} catch ( e ) {
850 push = { apply: arr.length ?
851
852 // Leverage slice if possible
853 function( target, els ) {
854 push_native.apply( target, slice.call(els) );
855 } :
856
857 // Support: IE<9
858 // Otherwise append directly
859 function( target, els ) {
860 var j = target.length,
861 i = 0;
862 // Can't trust NodeList.length
863 while ( (target[j++] = els[i++]) ) {}
864 target.length = j - 1;
865 }
866 };
867}
868
869function Sizzle( selector, context, results, seed ) {
870 var match, elem, m, nodeType,
871 // QSA vars
872 i, groups, old, nid, newContext, newSelector;
873
874 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
875 setDocument( context );
876 }
877
878 context = context || document;
879 results = results || [];
880
881 if ( !selector || typeof selector !== "string" ) {
882 return results;
883 }
884
885 if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
886 return [];
887 }
888
889 if ( documentIsHTML && !seed ) {
890
891 // Shortcuts
892 if ( (match = rquickExpr.exec( selector )) ) {
893 // Speed-up: Sizzle("#ID")
894 if ( (m = match[1]) ) {
895 if ( nodeType === 9 ) {
896 elem = context.getElementById( m );
897 // Check parentNode to catch when Blackberry 4.6 returns
898 // nodes that are no longer in the document (jQuery #6963)
899 if ( elem && elem.parentNode ) {
900 // Handle the case where IE, Opera, and Webkit return items
901 // by name instead of ID
902 if ( elem.id === m ) {
903 results.push( elem );
904 return results;
905 }
906 } else {
907 return results;
908 }
909 } else {
910 // Context is not a document
911 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
912 contains( context, elem ) && elem.id === m ) {
913 results.push( elem );
914 return results;
915 }
916 }
917
918 // Speed-up: Sizzle("TAG")
919 } else if ( match[2] ) {
920 push.apply( results, context.getElementsByTagName( selector ) );
921 return results;
922
923 // Speed-up: Sizzle(".CLASS")
924 } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
925 push.apply( results, context.getElementsByClassName( m ) );
926 return results;
927 }
928 }
929
930 // QSA path
931 if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
932 nid = old = expando;
933 newContext = context;
934 newSelector = nodeType === 9 && selector;
935
936 // qSA works strangely on Element-rooted queries
937 // We can work around this by specifying an extra ID on the root
938 // and working up from there (Thanks to Andrew Dupont for the technique)
939 // IE 8 doesn't work on object elements
940 if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
941 groups = tokenize( selector );
942
943 if ( (old = context.getAttribute("id")) ) {
944 nid = old.replace( rescape, "\\$&" );
945 } else {
946 context.setAttribute( "id", nid );
947 }
948 nid = "[id='" + nid + "'] ";
949
950 i = groups.length;
951 while ( i-- ) {
952 groups[i] = nid + toSelector( groups[i] );
953 }
954 newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
955 newSelector = groups.join(",");
956 }
957
958 if ( newSelector ) {
959 try {
960 push.apply( results,
961 newContext.querySelectorAll( newSelector )
962 );
963 return results;
964 } catch(qsaError) {
965 } finally {
966 if ( !old ) {
967 context.removeAttribute("id");
968 }
969 }
970 }
971 }
972 }
973
974 // All others
975 return select( selector.replace( rtrim, "$1" ), context, results, seed );
976}
977
978/**
979 * Create key-value caches of limited size
980 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
981 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
982 * deleting the oldest entry
983 */
984function createCache() {
985 var keys = [];
986
987 function cache( key, value ) {
988 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
989 if ( keys.push( key + " " ) > Expr.cacheLength ) {
990 // Only keep the most recent entries
991 delete cache[ keys.shift() ];
992 }
993 return (cache[ key + " " ] = value);
994 }
995 return cache;
996}
997
998/**
999 * Mark a function for special use by Sizzle
1000 * @param {Function} fn The function to mark
1001 */
1002function markFunction( fn ) {
1003 fn[ expando ] = true;
1004 return fn;
1005}
1006
1007/**
1008 * Support testing using an element
1009 * @param {Function} fn Passed the created div and expects a boolean result
1010 */
1011function assert( fn ) {
1012 var div = document.createElement("div");
1013
1014 try {
1015 return !!fn( div );
1016 } catch (e) {
1017 return false;
1018 } finally {
1019 // Remove from its parent by default
1020 if ( div.parentNode ) {
1021 div.parentNode.removeChild( div );
1022 }
1023 // release memory in IE
1024 div = null;
1025 }
1026}
1027
1028/**
1029 * Adds the same handler for all of the specified attrs
1030 * @param {String} attrs Pipe-separated list of attributes
1031 * @param {Function} handler The method that will be applied
1032 */
1033function addHandle( attrs, handler ) {
1034 var arr = attrs.split("|"),
1035 i = attrs.length;
1036
1037 while ( i-- ) {
1038 Expr.attrHandle[ arr[i] ] = handler;
1039 }
1040}
1041
1042/**
1043 * Checks document order of two siblings
1044 * @param {Element} a
1045 * @param {Element} b
1046 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
1047 */
1048function siblingCheck( a, b ) {
1049 var cur = b && a,
1050 diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
1051 ( ~b.sourceIndex || MAX_NEGATIVE ) -
1052 ( ~a.sourceIndex || MAX_NEGATIVE );
1053
1054 // Use IE sourceIndex if available on both nodes
1055 if ( diff ) {
1056 return diff;
1057 }
1058
1059 // Check if b follows a
1060 if ( cur ) {
1061 while ( (cur = cur.nextSibling) ) {
1062 if ( cur === b ) {
1063 return -1;
1064 }
1065 }
1066 }
1067
1068 return a ? 1 : -1;
1069}
1070
1071/**
1072 * Returns a function to use in pseudos for input types
1073 * @param {String} type
1074 */
1075function createInputPseudo( type ) {
1076 return function( elem ) {
1077 var name = elem.nodeName.toLowerCase();
1078 return name === "input" && elem.type === type;
1079 };
1080}
1081
1082/**
1083 * Returns a function to use in pseudos for buttons
1084 * @param {String} type
1085 */
1086function createButtonPseudo( type ) {
1087 return function( elem ) {
1088 var name = elem.nodeName.toLowerCase();
1089 return (name === "input" || name === "button") && elem.type === type;
1090 };
1091}
1092
1093/**
1094 * Returns a function to use in pseudos for positionals
1095 * @param {Function} fn
1096 */
1097function createPositionalPseudo( fn ) {
1098 return markFunction(function( argument ) {
1099 argument = +argument;
1100 return markFunction(function( seed, matches ) {
1101 var j,
1102 matchIndexes = fn( [], seed.length, argument ),
1103 i = matchIndexes.length;
1104
1105 // Match elements found at the specified indexes
1106 while ( i-- ) {
1107 if ( seed[ (j = matchIndexes[i]) ] ) {
1108 seed[j] = !(matches[j] = seed[j]);
1109 }
1110 }
1111 });
1112 });
1113}
1114
1115/**
1116 * Checks a node for validity as a Sizzle context
1117 * @param {Element|Object=} context
1118 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
1119 */
1120function testContext( context ) {
1121 return context && typeof context.getElementsByTagName !== strundefined && context;
1122}
1123
1124// Expose support vars for convenience
1125support = Sizzle.support = {};
1126
1127/**
1128 * Detects XML nodes
1129 * @param {Element|Object} elem An element or a document
1130 * @returns {Boolean} True iff elem is a non-HTML XML node
1131 */
1132isXML = Sizzle.isXML = function( elem ) {
1133 // documentElement is verified for cases where it doesn't yet exist
1134 // (such as loading iframes in IE - #4833)
1135 var documentElement = elem && (elem.ownerDocument || elem).documentElement;
1136 return documentElement ? documentElement.nodeName !== "HTML" : false;
1137};
1138
1139/**
1140 * Sets document-related variables once based on the current document
1141 * @param {Element|Object} [doc] An element or document object to use to set the document
1142 * @returns {Object} Returns the current document
1143 */
1144setDocument = Sizzle.setDocument = function( node ) {
1145 var hasCompare,
1146 doc = node ? node.ownerDocument || node : preferredDoc,
1147 parent = doc.defaultView;
1148
1149 // If no document and documentElement is available, return
1150 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1151 return document;
1152 }
1153
1154 // Set our document
1155 document = doc;
1156 docElem = doc.documentElement;
1157
1158 // Support tests
1159 documentIsHTML = !isXML( doc );
1160
1161 // Support: IE>8
1162 // If iframe document is assigned to "document" variable and if iframe has been reloaded,
1163 // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
1164 // IE6-8 do not support the defaultView property so parent will be undefined
1165 if ( parent && parent !== parent.top ) {
1166 // IE11 does not have attachEvent, so all must suffer
1167 if ( parent.addEventListener ) {
1168 parent.addEventListener( "unload", function() {
1169 setDocument();
1170 }, false );
1171 } else if ( parent.attachEvent ) {
1172 parent.attachEvent( "onunload", function() {
1173 setDocument();
1174 });
1175 }
1176 }
1177
1178 /* Attributes
1179 ---------------------------------------------------------------------- */
1180
1181 // Support: IE<8
1182 // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
1183 support.attributes = assert(function( div ) {
1184 div.className = "i";
1185 return !div.getAttribute("className");
1186 });
1187
1188 /* getElement(s)By*
1189 ---------------------------------------------------------------------- */
1190
1191 // Check if getElementsByTagName("*") returns only elements
1192 support.getElementsByTagName = assert(function( div ) {
1193 div.appendChild( doc.createComment("") );
1194 return !div.getElementsByTagName("*").length;
1195 });
1196
1197 // Check if getElementsByClassName can be trusted
1198 support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
1199 div.innerHTML = "<div class='a'></div><div class='a i'></div>";
1200
1201 // Support: Safari<4
1202 // Catch class over-caching
1203 div.firstChild.className = "i";
1204 // Support: Opera<10
1205 // Catch gEBCN failure to find non-leading classes
1206 return div.getElementsByClassName("i").length === 2;
1207 });
1208
1209 // Support: IE<10
1210 // Check if getElementById returns elements by name
1211 // The broken getElementById methods don't pick up programatically-set names,
1212 // so use a roundabout getElementsByName test
1213 support.getById = assert(function( div ) {
1214 docElem.appendChild( div ).id = expando;
1215 return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
1216 });
1217
1218 // ID find and filter
1219 if ( support.getById ) {
1220 Expr.find["ID"] = function( id, context ) {
1221 if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
1222 var m = context.getElementById( id );
1223 // Check parentNode to catch when Blackberry 4.6 returns
1224 // nodes that are no longer in the document #6963
1225 return m && m.parentNode ? [ m ] : [];
1226 }
1227 };
1228 Expr.filter["ID"] = function( id ) {
1229 var attrId = id.replace( runescape, funescape );
1230 return function( elem ) {
1231 return elem.getAttribute("id") === attrId;
1232 };
1233 };
1234 } else {
1235 // Support: IE6/7
1236 // getElementById is not reliable as a find shortcut
1237 delete Expr.find["ID"];
1238
1239 Expr.filter["ID"] = function( id ) {
1240 var attrId = id.replace( runescape, funescape );
1241 return function( elem ) {
1242 var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
1243 return node && node.value === attrId;
1244 };
1245 };
1246 }
1247
1248 // Tag
1249 Expr.find["TAG"] = support.getElementsByTagName ?
1250 function( tag, context ) {
1251 if ( typeof context.getElementsByTagName !== strundefined ) {
1252 return context.getElementsByTagName( tag );
1253 }
1254 } :
1255 function( tag, context ) {
1256 var elem,
1257 tmp = [],
1258 i = 0,
1259 results = context.getElementsByTagName( tag );
1260
1261 // Filter out possible comments
1262 if ( tag === "*" ) {
1263 while ( (elem = results[i++]) ) {
1264 if ( elem.nodeType === 1 ) {
1265 tmp.push( elem );
1266 }
1267 }
1268
1269 return tmp;
1270 }
1271 return results;
1272 };
1273
1274 // Class
1275 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
1276 if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
1277 return context.getElementsByClassName( className );
1278 }
1279 };
1280
1281 /* QSA/matchesSelector
1282 ---------------------------------------------------------------------- */
1283
1284 // QSA and matchesSelector support
1285
1286 // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1287 rbuggyMatches = [];
1288
1289 // qSa(:focus) reports false when true (Chrome 21)
1290 // We allow this because of a bug in IE8/9 that throws an error
1291 // whenever `document.activeElement` is accessed on an iframe
1292 // So, we allow :focus to pass through QSA all the time to avoid the IE error
1293 // See http://bugs.jquery.com/ticket/13378
1294 rbuggyQSA = [];
1295
1296 if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
1297 // Build QSA regex
1298 // Regex strategy adopted from Diego Perini
1299 assert(function( div ) {
1300 // Select is set to empty string on purpose
1301 // This is to test IE's treatment of not explicitly
1302 // setting a boolean content attribute,
1303 // since its presence should be enough
1304 // http://bugs.jquery.com/ticket/12359
1305 div.innerHTML = "<select msallowclip=''><option selected=''></option></select>";
1306
1307 // Support: IE8, Opera 11-12.16
1308 // Nothing should be selected when empty strings follow ^= or $= or *=
1309 // The test attribute must be unknown in Opera but "safe" for WinRT
1310 // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
1311 if ( div.querySelectorAll("[msallowclip^='']").length ) {
1312 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1313 }
1314
1315 // Support: IE8
1316 // Boolean attributes and "value" are not treated correctly
1317 if ( !div.querySelectorAll("[selected]").length ) {
1318 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1319 }
1320
1321 // Webkit/Opera - :checked should return selected option elements
1322 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1323 // IE8 throws error here and will not see later tests
1324 if ( !div.querySelectorAll(":checked").length ) {
1325 rbuggyQSA.push(":checked");
1326 }
1327 });
1328
1329 assert(function( div ) {
1330 // Support: Windows 8 Native Apps
1331 // The type and name attributes are restricted during .innerHTML assignment
1332 var input = doc.createElement("input");
1333 input.setAttribute( "type", "hidden" );
1334 div.appendChild( input ).setAttribute( "name", "D" );
1335
1336 // Support: IE8
1337 // Enforce case-sensitivity of name attribute
1338 if ( div.querySelectorAll("[name=d]").length ) {
1339 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
1340 }
1341
1342 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1343 // IE8 throws error here and will not see later tests
1344 if ( !div.querySelectorAll(":enabled").length ) {
1345 rbuggyQSA.push( ":enabled", ":disabled" );
1346 }
1347
1348 // Opera 10-11 does not throw on post-comma invalid pseudos
1349 div.querySelectorAll("*,:x");
1350 rbuggyQSA.push(",.*:");
1351 });
1352 }
1353
1354 if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
1355 docElem.webkitMatchesSelector ||
1356 docElem.mozMatchesSelector ||
1357 docElem.oMatchesSelector ||
1358 docElem.msMatchesSelector) )) ) {
1359
1360 assert(function( div ) {
1361 // Check to see if it's possible to do matchesSelector
1362 // on a disconnected node (IE 9)
1363 support.disconnectedMatch = matches.call( div, "div" );
1364
1365 // This should fail with an exception
1366 // Gecko does not error, returns false instead
1367 matches.call( div, "[s!='']:x" );
1368 rbuggyMatches.push( "!=", pseudos );
1369 });
1370 }
1371
1372 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
1373 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
1374
1375 /* Contains
1376 ---------------------------------------------------------------------- */
1377 hasCompare = rnative.test( docElem.compareDocumentPosition );
1378
1379 // Element contains another
1380 // Purposefully does not implement inclusive descendent
1381 // As in, an element does not contain itself
1382 contains = hasCompare || rnative.test( docElem.contains ) ?
1383 function( a, b ) {
1384 var adown = a.nodeType === 9 ? a.documentElement : a,
1385 bup = b && b.parentNode;
1386 return a === bup || !!( bup && bup.nodeType === 1 && (
1387 adown.contains ?
1388 adown.contains( bup ) :
1389 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1390 ));
1391 } :
1392 function( a, b ) {
1393 if ( b ) {
1394 while ( (b = b.parentNode) ) {
1395 if ( b === a ) {
1396 return true;
1397 }
1398 }
1399 }
1400 return false;
1401 };
1402
1403 /* Sorting
1404 ---------------------------------------------------------------------- */
1405
1406 // Document order sorting
1407 sortOrder = hasCompare ?
1408 function( a, b ) {
1409
1410 // Flag for duplicate removal
1411 if ( a === b ) {
1412 hasDuplicate = true;
1413 return 0;
1414 }
1415
1416 // Sort on method existence if only one input has compareDocumentPosition
1417 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1418 if ( compare ) {
1419 return compare;
1420 }
1421
1422 // Calculate position if both inputs belong to the same document
1423 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
1424 a.compareDocumentPosition( b ) :
1425
1426 // Otherwise we know they are disconnected
1427 1;
1428
1429 // Disconnected nodes
1430 if ( compare & 1 ||
1431 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
1432
1433 // Choose the first element that is related to our preferred document
1434 if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
1435 return -1;
1436 }
1437 if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
1438 return 1;
1439 }
1440
1441 // Maintain original order
1442 return sortInput ?
1443 ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
1444 0;
1445 }
1446
1447 return compare & 4 ? -1 : 1;
1448 } :
1449 function( a, b ) {
1450 // Exit early if the nodes are identical
1451 if ( a === b ) {
1452 hasDuplicate = true;
1453 return 0;
1454 }
1455
1456 var cur,
1457 i = 0,
1458 aup = a.parentNode,
1459 bup = b.parentNode,
1460 ap = [ a ],
1461 bp = [ b ];
1462
1463 // Parentless nodes are either documents or disconnected
1464 if ( !aup || !bup ) {
1465 return a === doc ? -1 :
1466 b === doc ? 1 :
1467 aup ? -1 :
1468 bup ? 1 :
1469 sortInput ?
1470 ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
1471 0;
1472
1473 // If the nodes are siblings, we can do a quick check
1474 } else if ( aup === bup ) {
1475 return siblingCheck( a, b );
1476 }
1477
1478 // Otherwise we need full lists of their ancestors for comparison
1479 cur = a;
1480 while ( (cur = cur.parentNode) ) {
1481 ap.unshift( cur );
1482 }
1483 cur = b;
1484 while ( (cur = cur.parentNode) ) {
1485 bp.unshift( cur );
1486 }
1487
1488 // Walk down the tree looking for a discrepancy
1489 while ( ap[i] === bp[i] ) {
1490 i++;
1491 }
1492
1493 return i ?
1494 // Do a sibling check if the nodes have a common ancestor
1495 siblingCheck( ap[i], bp[i] ) :
1496
1497 // Otherwise nodes in our document sort first
1498 ap[i] === preferredDoc ? -1 :
1499 bp[i] === preferredDoc ? 1 :
1500 0;
1501 };
1502
1503 return doc;
1504};
1505
1506Sizzle.matches = function( expr, elements ) {
1507 return Sizzle( expr, null, null, elements );
1508};
1509
1510Sizzle.matchesSelector = function( elem, expr ) {
1511 // Set document vars if needed
1512 if ( ( elem.ownerDocument || elem ) !== document ) {
1513 setDocument( elem );
1514 }
1515
1516 // Make sure that attribute selectors are quoted
1517 expr = expr.replace( rattributeQuotes, "='$1']" );
1518
1519 if ( support.matchesSelector && documentIsHTML &&
1520 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1521 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
1522
1523 try {
1524 var ret = matches.call( elem, expr );
1525
1526 // IE 9's matchesSelector returns false on disconnected nodes
1527 if ( ret || support.disconnectedMatch ||
1528 // As well, disconnected nodes are said to be in a document
1529 // fragment in IE 9
1530 elem.document && elem.document.nodeType !== 11 ) {
1531 return ret;
1532 }
1533 } catch(e) {}
1534 }
1535
1536 return Sizzle( expr, document, null, [ elem ] ).length > 0;
1537};
1538
1539Sizzle.contains = function( context, elem ) {
1540 // Set document vars if needed
1541 if ( ( context.ownerDocument || context ) !== document ) {
1542 setDocument( context );
1543 }
1544 return contains( context, elem );
1545};
1546
1547Sizzle.attr = function( elem, name ) {
1548 // Set document vars if needed
1549 if ( ( elem.ownerDocument || elem ) !== document ) {
1550 setDocument( elem );
1551 }
1552
1553 var fn = Expr.attrHandle[ name.toLowerCase() ],
1554 // Don't get fooled by Object.prototype properties (jQuery #13807)
1555 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1556 fn( elem, name, !documentIsHTML ) :
1557 undefined;
1558
1559 return val !== undefined ?
1560 val :
1561 support.attributes || !documentIsHTML ?
1562 elem.getAttribute( name ) :
1563 (val = elem.getAttributeNode(name)) && val.specified ?
1564 val.value :
1565 null;
1566};
1567
1568Sizzle.error = function( msg ) {
1569 throw new Error( "Syntax error, unrecognized expression: " + msg );
1570};
1571
1572/**
1573 * Document sorting and removing duplicates
1574 * @param {ArrayLike} results
1575 */
1576Sizzle.uniqueSort = function( results ) {
1577 var elem,
1578 duplicates = [],
1579 j = 0,
1580 i = 0;
1581
1582 // Unless we *know* we can detect duplicates, assume their presence
1583 hasDuplicate = !support.detectDuplicates;
1584 sortInput = !support.sortStable && results.slice( 0 );
1585 results.sort( sortOrder );
1586
1587 if ( hasDuplicate ) {
1588 while ( (elem = results[i++]) ) {
1589 if ( elem === results[ i ] ) {
1590 j = duplicates.push( i );
1591 }
1592 }
1593 while ( j-- ) {
1594 results.splice( duplicates[ j ], 1 );
1595 }
1596 }
1597
1598 // Clear input after sorting to release objects
1599 // See https://github.com/jquery/sizzle/pull/225
1600 sortInput = null;
1601
1602 return results;
1603};
1604
1605/**
1606 * Utility function for retrieving the text value of an array of DOM nodes
1607 * @param {Array|Element} elem
1608 */
1609getText = Sizzle.getText = function( elem ) {
1610 var node,
1611 ret = "",
1612 i = 0,
1613 nodeType = elem.nodeType;
1614
1615 if ( !nodeType ) {
1616 // If no nodeType, this is expected to be an array
1617 while ( (node = elem[i++]) ) {
1618 // Do not traverse comment nodes
1619 ret += getText( node );
1620 }
1621 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1622 // Use textContent for elements
1623 // innerText usage removed for consistency of new lines (jQuery #11153)
1624 if ( typeof elem.textContent === "string" ) {
1625 return elem.textContent;
1626 } else {
1627 // Traverse its children
1628 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1629 ret += getText( elem );
1630 }
1631 }
1632 } else if ( nodeType === 3 || nodeType === 4 ) {
1633 return elem.nodeValue;
1634 }
1635 // Do not include comment or processing instruction nodes
1636
1637 return ret;
1638};
1639
1640Expr = Sizzle.selectors = {
1641
1642 // Can be adjusted by the user
1643 cacheLength: 50,
1644
1645 createPseudo: markFunction,
1646
1647 match: matchExpr,
1648
1649 attrHandle: {},
1650
1651 find: {},
1652
1653 relative: {
1654 ">": { dir: "parentNode", first: true },
1655 " ": { dir: "parentNode" },
1656 "+": { dir: "previousSibling", first: true },
1657 "~": { dir: "previousSibling" }
1658 },
1659
1660 preFilter: {
1661 "ATTR": function( match ) {
1662 match[1] = match[1].replace( runescape, funescape );
1663
1664 // Move the given value to match[3] whether quoted or unquoted
1665 match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
1666
1667 if ( match[2] === "~=" ) {
1668 match[3] = " " + match[3] + " ";
1669 }
1670
1671 return match.slice( 0, 4 );
1672 },
1673
1674 "CHILD": function( match ) {
1675 /* matches from matchExpr["CHILD"]
1676 1 type (only|nth|...)
1677 2 what (child|of-type)
1678 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1679 4 xn-component of xn+y argument ([+-]?\d*n|)
1680 5 sign of xn-component
1681 6 x of xn-component
1682 7 sign of y-component
1683 8 y of y-component
1684 */
1685 match[1] = match[1].toLowerCase();
1686
1687 if ( match[1].slice( 0, 3 ) === "nth" ) {
1688 // nth-* requires argument
1689 if ( !match[3] ) {
1690 Sizzle.error( match[0] );
1691 }
1692
1693 // numeric x and y parameters for Expr.filter.CHILD
1694 // remember that false/true cast respectively to 0/1
1695 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1696 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
1697
1698 // other types prohibit arguments
1699 } else if ( match[3] ) {
1700 Sizzle.error( match[0] );
1701 }
1702
1703 return match;
1704 },
1705
1706 "PSEUDO": function( match ) {
1707 var excess,
1708 unquoted = !match[6] && match[2];
1709
1710 if ( matchExpr["CHILD"].test( match[0] ) ) {
1711 return null;
1712 }
1713
1714 // Accept quoted arguments as-is
1715 if ( match[3] ) {
1716 match[2] = match[4] || match[5] || "";
1717
1718 // Strip excess characters from unquoted arguments
1719 } else if ( unquoted && rpseudo.test( unquoted ) &&
1720 // Get excess from tokenize (recursively)
1721 (excess = tokenize( unquoted, true )) &&
1722 // advance to the next closing parenthesis
1723 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
1724
1725 // excess is a negative index
1726 match[0] = match[0].slice( 0, excess );
1727 match[2] = unquoted.slice( 0, excess );
1728 }
1729
1730 // Return only captures needed by the pseudo filter method (type and argument)
1731 return match.slice( 0, 3 );
1732 }
1733 },
1734
1735 filter: {
1736
1737 "TAG": function( nodeNameSelector ) {
1738 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1739 return nodeNameSelector === "*" ?
1740 function() { return true; } :
1741 function( elem ) {
1742 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1743 };
1744 },
1745
1746 "CLASS": function( className ) {
1747 var pattern = classCache[ className + " " ];
1748
1749 return pattern ||
1750 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
1751 classCache( className, function( elem ) {
1752 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
1753 });
1754 },
1755
1756 "ATTR": function( name, operator, check ) {
1757 return function( elem ) {
1758 var result = Sizzle.attr( elem, name );
1759
1760 if ( result == null ) {
1761 return operator === "!=";
1762 }
1763 if ( !operator ) {
1764 return true;
1765 }
1766
1767 result += "";
1768
1769 return operator === "=" ? result === check :
1770 operator === "!=" ? result !== check :
1771 operator === "^=" ? check && result.indexOf( check ) === 0 :
1772 operator === "*=" ? check && result.indexOf( check ) > -1 :
1773 operator === "$=" ? check && result.slice( -check.length ) === check :
1774 operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
1775 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
1776 false;
1777 };
1778 },
1779
1780 "CHILD": function( type, what, argument, first, last ) {
1781 var simple = type.slice( 0, 3 ) !== "nth",
1782 forward = type.slice( -4 ) !== "last",
1783 ofType = what === "of-type";
1784
1785 return first === 1 && last === 0 ?
1786
1787 // Shortcut for :nth-*(n)
1788 function( elem ) {
1789 return !!elem.parentNode;
1790 } :
1791
1792 function( elem, context, xml ) {
1793 var cache, outerCache, node, diff, nodeIndex, start,
1794 dir = simple !== forward ? "nextSibling" : "previousSibling",
1795 parent = elem.parentNode,
1796 name = ofType && elem.nodeName.toLowerCase(),
1797 useCache = !xml && !ofType;
1798
1799 if ( parent ) {
1800
1801 // :(first|last|only)-(child|of-type)
1802 if ( simple ) {
1803 while ( dir ) {
1804 node = elem;
1805 while ( (node = node[ dir ]) ) {
1806 if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
1807 return false;
1808 }
1809 }
1810 // Reverse direction for :only-* (if we haven't yet done so)
1811 start = dir = type === "only" && !start && "nextSibling";
1812 }
1813 return true;
1814 }
1815
1816 start = [ forward ? parent.firstChild : parent.lastChild ];
1817
1818 // non-xml :nth-child(...) stores cache data on `parent`
1819 if ( forward && useCache ) {
1820 // Seek `elem` from a previously-cached index
1821 outerCache = parent[ expando ] || (parent[ expando ] = {});
1822 cache = outerCache[ type ] || [];
1823 nodeIndex = cache[0] === dirruns && cache[1];
1824 diff = cache[0] === dirruns && cache[2];
1825 node = nodeIndex && parent.childNodes[ nodeIndex ];
1826
1827 while ( (node = ++nodeIndex && node && node[ dir ] ||
1828
1829 // Fallback to seeking `elem` from the start
1830 (diff = nodeIndex = 0) || start.pop()) ) {
1831
1832 // When found, cache indexes on `parent` and break
1833 if ( node.nodeType === 1 && ++diff && node === elem ) {
1834 outerCache[ type ] = [ dirruns, nodeIndex, diff ];
1835 break;
1836 }
1837 }
1838
1839 // Use previously-cached element index if available
1840 } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
1841 diff = cache[1];
1842
1843 // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
1844 } else {
1845 // Use the same loop as above to seek `elem` from the start
1846 while ( (node = ++nodeIndex && node && node[ dir ] ||
1847 (diff = nodeIndex = 0) || start.pop()) ) {
1848
1849 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
1850 // Cache the index of each encountered element
1851 if ( useCache ) {
1852 (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
1853 }
1854
1855 if ( node === elem ) {
1856 break;
1857 }
1858 }
1859 }
1860 }
1861
1862 // Incorporate the offset, then check against cycle size
1863 diff -= last;
1864 return diff === first || ( diff % first === 0 && diff / first >= 0 );
1865 }
1866 };
1867 },
1868
1869 "PSEUDO": function( pseudo, argument ) {
1870 // pseudo-class names are case-insensitive
1871 // http://www.w3.org/TR/selectors/#pseudo-classes
1872 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1873 // Remember that setFilters inherits from pseudos
1874 var args,
1875 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1876 Sizzle.error( "unsupported pseudo: " + pseudo );
1877
1878 // The user may use createPseudo to indicate that
1879 // arguments are needed to create the filter function
1880 // just as Sizzle does
1881 if ( fn[ expando ] ) {
1882 return fn( argument );
1883 }
1884
1885 // But maintain support for old signatures
1886 if ( fn.length > 1 ) {
1887 args = [ pseudo, pseudo, "", argument ];
1888 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1889 markFunction(function( seed, matches ) {
1890 var idx,
1891 matched = fn( seed, argument ),
1892 i = matched.length;
1893 while ( i-- ) {
1894 idx = indexOf.call( seed, matched[i] );
1895 seed[ idx ] = !( matches[ idx ] = matched[i] );
1896 }
1897 }) :
1898 function( elem ) {
1899 return fn( elem, 0, args );
1900 };
1901 }
1902
1903 return fn;
1904 }
1905 },
1906
1907 pseudos: {
1908 // Potentially complex pseudos
1909 "not": markFunction(function( selector ) {
1910 // Trim the selector passed to compile
1911 // to avoid treating leading and trailing
1912 // spaces as combinators
1913 var input = [],
1914 results = [],
1915 matcher = compile( selector.replace( rtrim, "$1" ) );
1916
1917 return matcher[ expando ] ?
1918 markFunction(function( seed, matches, context, xml ) {
1919 var elem,
1920 unmatched = matcher( seed, null, xml, [] ),
1921 i = seed.length;
1922
1923 // Match elements unmatched by `matcher`
1924 while ( i-- ) {
1925 if ( (elem = unmatched[i]) ) {
1926 seed[i] = !(matches[i] = elem);
1927 }
1928 }
1929 }) :
1930 function( elem, context, xml ) {
1931 input[0] = elem;
1932 matcher( input, null, xml, results );
1933 return !results.pop();
1934 };
1935 }),
1936
1937 "has": markFunction(function( selector ) {
1938 return function( elem ) {
1939 return Sizzle( selector, elem ).length > 0;
1940 };
1941 }),
1942
1943 "contains": markFunction(function( text ) {
1944 return function( elem ) {
1945 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
1946 };
1947 }),
1948
1949 // "Whether an element is represented by a :lang() selector
1950 // is based solely on the element's language value
1951 // being equal to the identifier C,
1952 // or beginning with the identifier C immediately followed by "-".
1953 // The matching of C against the element's language value is performed case-insensitively.
1954 // The identifier C does not have to be a valid language name."
1955 // http://www.w3.org/TR/selectors/#lang-pseudo
1956 "lang": markFunction( function( lang ) {
1957 // lang value must be a valid identifier
1958 if ( !ridentifier.test(lang || "") ) {
1959 Sizzle.error( "unsupported lang: " + lang );
1960 }
1961 lang = lang.replace( runescape, funescape ).toLowerCase();
1962 return function( elem ) {
1963 var elemLang;
1964 do {
1965 if ( (elemLang = documentIsHTML ?
1966 elem.lang :
1967 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
1968
1969 elemLang = elemLang.toLowerCase();
1970 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
1971 }
1972 } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
1973 return false;
1974 };
1975 }),
1976
1977 // Miscellaneous
1978 "target": function( elem ) {
1979 var hash = window.location && window.location.hash;
1980 return hash && hash.slice( 1 ) === elem.id;
1981 },
1982
1983 "root": function( elem ) {
1984 return elem === docElem;
1985 },
1986
1987 "focus": function( elem ) {
1988 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
1989 },
1990
1991 // Boolean properties
1992 "enabled": function( elem ) {
1993 return elem.disabled === false;
1994 },
1995
1996 "disabled": function( elem ) {
1997 return elem.disabled === true;
1998 },
1999
2000 "checked": function( elem ) {
2001 // In CSS3, :checked should return both checked and selected elements
2002 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
2003 var nodeName = elem.nodeName.toLowerCase();
2004 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
2005 },
2006
2007 "selected": function( elem ) {
2008 // Accessing this property makes selected-by-default
2009 // options in Safari work properly
2010 if ( elem.parentNode ) {
2011 elem.parentNode.selectedIndex;
2012 }
2013
2014 return elem.selected === true;
2015 },
2016
2017 // Contents
2018 "empty": function( elem ) {
2019 // http://www.w3.org/TR/selectors/#empty-pseudo
2020 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
2021 // but not by others (comment: 8; processing instruction: 7; etc.)
2022 // nodeType < 6 works because attributes (2) do not appear as children
2023 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
2024 if ( elem.nodeType < 6 ) {
2025 return false;
2026 }
2027 }
2028 return true;
2029 },
2030
2031 "parent": function( elem ) {
2032 return !Expr.pseudos["empty"]( elem );
2033 },
2034
2035 // Element/input types
2036 "header": function( elem ) {
2037 return rheader.test( elem.nodeName );
2038 },
2039
2040 "input": function( elem ) {
2041 return rinputs.test( elem.nodeName );
2042 },
2043
2044 "button": function( elem ) {
2045 var name = elem.nodeName.toLowerCase();
2046 return name === "input" && elem.type === "button" || name === "button";
2047 },
2048
2049 "text": function( elem ) {
2050 var attr;
2051 return elem.nodeName.toLowerCase() === "input" &&
2052 elem.type === "text" &&
2053
2054 // Support: IE<8
2055 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
2056 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
2057 },
2058
2059 // Position-in-collection
2060 "first": createPositionalPseudo(function() {
2061 return [ 0 ];
2062 }),
2063
2064 "last": createPositionalPseudo(function( matchIndexes, length ) {
2065 return [ length - 1 ];
2066 }),
2067
2068 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
2069 return [ argument < 0 ? argument + length : argument ];
2070 }),
2071
2072 "even": createPositionalPseudo(function( matchIndexes, length ) {
2073 var i = 0;
2074 for ( ; i < length; i += 2 ) {
2075 matchIndexes.push( i );
2076 }
2077 return matchIndexes;
2078 }),
2079
2080 "odd": createPositionalPseudo(function( matchIndexes, length ) {
2081 var i = 1;
2082 for ( ; i < length; i += 2 ) {
2083 matchIndexes.push( i );
2084 }
2085 return matchIndexes;
2086 }),
2087
2088 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2089 var i = argument < 0 ? argument + length : argument;
2090 for ( ; --i >= 0; ) {
2091 matchIndexes.push( i );
2092 }
2093 return matchIndexes;
2094 }),
2095
2096 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2097 var i = argument < 0 ? argument + length : argument;
2098 for ( ; ++i < length; ) {
2099 matchIndexes.push( i );
2100 }
2101 return matchIndexes;
2102 })
2103 }
2104};
2105
2106Expr.pseudos["nth"] = Expr.pseudos["eq"];
2107
2108// Add button/input type pseudos
2109for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2110 Expr.pseudos[ i ] = createInputPseudo( i );
2111}
2112for ( i in { submit: true, reset: true } ) {
2113 Expr.pseudos[ i ] = createButtonPseudo( i );
2114}
2115
2116// Easy API for creating new setFilters
2117function setFilters() {}
2118setFilters.prototype = Expr.filters = Expr.pseudos;
2119Expr.setFilters = new setFilters();
2120
2121tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2122 var matched, match, tokens, type,
2123 soFar, groups, preFilters,
2124 cached = tokenCache[ selector + " " ];
2125
2126 if ( cached ) {
2127 return parseOnly ? 0 : cached.slice( 0 );
2128 }
2129
2130 soFar = selector;
2131 groups = [];
2132 preFilters = Expr.preFilter;
2133
2134 while ( soFar ) {
2135
2136 // Comma and first run
2137 if ( !matched || (match = rcomma.exec( soFar )) ) {
2138 if ( match ) {
2139 // Don't consume trailing commas as valid
2140 soFar = soFar.slice( match[0].length ) || soFar;
2141 }
2142 groups.push( (tokens = []) );
2143 }
2144
2145 matched = false;
2146
2147 // Combinators
2148 if ( (match = rcombinators.exec( soFar )) ) {
2149 matched = match.shift();
2150 tokens.push({
2151 value: matched,
2152 // Cast descendant combinators to space
2153 type: match[0].replace( rtrim, " " )
2154 });
2155 soFar = soFar.slice( matched.length );
2156 }
2157
2158 // Filters
2159 for ( type in Expr.filter ) {
2160 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
2161 (match = preFilters[ type ]( match ))) ) {
2162 matched = match.shift();
2163 tokens.push({
2164 value: matched,
2165 type: type,
2166 matches: match
2167 });
2168 soFar = soFar.slice( matched.length );
2169 }
2170 }
2171
2172 if ( !matched ) {
2173 break;
2174 }
2175 }
2176
2177 // Return the length of the invalid excess
2178 // if we're just parsing
2179 // Otherwise, throw an error or return tokens
2180 return parseOnly ?
2181 soFar.length :
2182 soFar ?
2183 Sizzle.error( selector ) :
2184 // Cache the tokens
2185 tokenCache( selector, groups ).slice( 0 );
2186};
2187
2188function toSelector( tokens ) {
2189 var i = 0,
2190 len = tokens.length,
2191 selector = "";
2192 for ( ; i < len; i++ ) {
2193 selector += tokens[i].value;
2194 }
2195 return selector;
2196}
2197
2198function addCombinator( matcher, combinator, base ) {
2199 var dir = combinator.dir,
2200 checkNonElements = base && dir === "parentNode",
2201 doneName = done++;
2202
2203 return combinator.first ?
2204 // Check against closest ancestor/preceding element
2205 function( elem, context, xml ) {
2206 while ( (elem = elem[ dir ]) ) {
2207 if ( elem.nodeType === 1 || checkNonElements ) {
2208 return matcher( elem, context, xml );
2209 }
2210 }
2211 } :
2212
2213 // Check against all ancestor/preceding elements
2214 function( elem, context, xml ) {
2215 var oldCache, outerCache,
2216 newCache = [ dirruns, doneName ];
2217
2218 // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
2219 if ( xml ) {
2220 while ( (elem = elem[ dir ]) ) {
2221 if ( elem.nodeType === 1 || checkNonElements ) {
2222 if ( matcher( elem, context, xml ) ) {
2223 return true;
2224 }
2225 }
2226 }
2227 } else {
2228 while ( (elem = elem[ dir ]) ) {
2229 if ( elem.nodeType === 1 || checkNonElements ) {
2230 outerCache = elem[ expando ] || (elem[ expando ] = {});
2231 if ( (oldCache = outerCache[ dir ]) &&
2232 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2233
2234 // Assign to newCache so results back-propagate to previous elements
2235 return (newCache[ 2 ] = oldCache[ 2 ]);
2236 } else {
2237 // Reuse newcache so results back-propagate to previous elements
2238 outerCache[ dir ] = newCache;
2239
2240 // A match means we're done; a fail means we have to keep checking
2241 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
2242 return true;
2243 }
2244 }
2245 }
2246 }
2247 }
2248 };
2249}
2250
2251function elementMatcher( matchers ) {
2252 return matchers.length > 1 ?
2253 function( elem, context, xml ) {
2254 var i = matchers.length;
2255 while ( i-- ) {
2256 if ( !matchers[i]( elem, context, xml ) ) {
2257 return false;
2258 }
2259 }
2260 return true;
2261 } :
2262 matchers[0];
2263}
2264
2265function multipleContexts( selector, contexts, results ) {
2266 var i = 0,
2267 len = contexts.length;
2268 for ( ; i < len; i++ ) {
2269 Sizzle( selector, contexts[i], results );
2270 }
2271 return results;
2272}
2273
2274function condense( unmatched, map, filter, context, xml ) {
2275 var elem,
2276 newUnmatched = [],
2277 i = 0,
2278 len = unmatched.length,
2279 mapped = map != null;
2280
2281 for ( ; i < len; i++ ) {
2282 if ( (elem = unmatched[i]) ) {
2283 if ( !filter || filter( elem, context, xml ) ) {
2284 newUnmatched.push( elem );
2285 if ( mapped ) {
2286 map.push( i );
2287 }
2288 }
2289 }
2290 }
2291
2292 return newUnmatched;
2293}
2294
2295function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2296 if ( postFilter && !postFilter[ expando ] ) {
2297 postFilter = setMatcher( postFilter );
2298 }
2299 if ( postFinder && !postFinder[ expando ] ) {
2300 postFinder = setMatcher( postFinder, postSelector );
2301 }
2302 return markFunction(function( seed, results, context, xml ) {
2303 var temp, i, elem,
2304 preMap = [],
2305 postMap = [],
2306 preexisting = results.length,
2307
2308 // Get initial elements from seed or context
2309 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2310
2311 // Prefilter to get matcher input, preserving a map for seed-results synchronization
2312 matcherIn = preFilter && ( seed || !selector ) ?
2313 condense( elems, preMap, preFilter, context, xml ) :
2314 elems,
2315
2316 matcherOut = matcher ?
2317 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2318 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2319
2320 // ...intermediate processing is necessary
2321 [] :
2322
2323 // ...otherwise use results directly
2324 results :
2325 matcherIn;
2326
2327 // Find primary matches
2328 if ( matcher ) {
2329 matcher( matcherIn, matcherOut, context, xml );
2330 }
2331
2332 // Apply postFilter
2333 if ( postFilter ) {
2334 temp = condense( matcherOut, postMap );
2335 postFilter( temp, [], context, xml );
2336
2337 // Un-match failing elements by moving them back to matcherIn
2338 i = temp.length;
2339 while ( i-- ) {
2340 if ( (elem = temp[i]) ) {
2341 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
2342 }
2343 }
2344 }
2345
2346 if ( seed ) {
2347 if ( postFinder || preFilter ) {
2348 if ( postFinder ) {
2349 // Get the final matcherOut by condensing this intermediate into postFinder contexts
2350 temp = [];
2351 i = matcherOut.length;
2352 while ( i-- ) {
2353 if ( (elem = matcherOut[i]) ) {
2354 // Restore matcherIn since elem is not yet a final match
2355 temp.push( (matcherIn[i] = elem) );
2356 }
2357 }
2358 postFinder( null, (matcherOut = []), temp, xml );
2359 }
2360
2361 // Move matched elements from seed to results to keep them synchronized
2362 i = matcherOut.length;
2363 while ( i-- ) {
2364 if ( (elem = matcherOut[i]) &&
2365 (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
2366
2367 seed[temp] = !(results[temp] = elem);
2368 }
2369 }
2370 }
2371
2372 // Add elements to results, through postFinder if defined
2373 } else {
2374 matcherOut = condense(
2375 matcherOut === results ?
2376 matcherOut.splice( preexisting, matcherOut.length ) :
2377 matcherOut
2378 );
2379 if ( postFinder ) {
2380 postFinder( null, results, matcherOut, xml );
2381 } else {
2382 push.apply( results, matcherOut );
2383 }
2384 }
2385 });
2386}
2387
2388function matcherFromTokens( tokens ) {
2389 var checkContext, matcher, j,
2390 len = tokens.length,
2391 leadingRelative = Expr.relative[ tokens[0].type ],
2392 implicitRelative = leadingRelative || Expr.relative[" "],
2393 i = leadingRelative ? 1 : 0,
2394
2395 // The foundational matcher ensures that elements are reachable from top-level context(s)
2396 matchContext = addCombinator( function( elem ) {
2397 return elem === checkContext;
2398 }, implicitRelative, true ),
2399 matchAnyContext = addCombinator( function( elem ) {
2400 return indexOf.call( checkContext, elem ) > -1;
2401 }, implicitRelative, true ),
2402 matchers = [ function( elem, context, xml ) {
2403 return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2404 (checkContext = context).nodeType ?
2405 matchContext( elem, context, xml ) :
2406 matchAnyContext( elem, context, xml ) );
2407 } ];
2408
2409 for ( ; i < len; i++ ) {
2410 if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
2411 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
2412 } else {
2413 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
2414
2415 // Return special upon seeing a positional matcher
2416 if ( matcher[ expando ] ) {
2417 // Find the next relative operator (if any) for proper handling
2418 j = ++i;
2419 for ( ; j < len; j++ ) {
2420 if ( Expr.relative[ tokens[j].type ] ) {
2421 break;
2422 }
2423 }
2424 return setMatcher(
2425 i > 1 && elementMatcher( matchers ),
2426 i > 1 && toSelector(
2427 // If the preceding token was a descendant combinator, insert an implicit any-element `*`
2428 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2429 ).replace( rtrim, "$1" ),
2430 matcher,
2431 i < j && matcherFromTokens( tokens.slice( i, j ) ),
2432 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
2433 j < len && toSelector( tokens )
2434 );
2435 }
2436 matchers.push( matcher );
2437 }
2438 }
2439
2440 return elementMatcher( matchers );
2441}
2442
2443function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2444 var bySet = setMatchers.length > 0,
2445 byElement = elementMatchers.length > 0,
2446 superMatcher = function( seed, context, xml, results, outermost ) {
2447 var elem, j, matcher,
2448 matchedCount = 0,
2449 i = "0",
2450 unmatched = seed && [],
2451 setMatched = [],
2452 contextBackup = outermostContext,
2453 // We must always have either seed elements or outermost context
2454 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
2455 // Use integer dirruns iff this is the outermost matcher
2456 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
2457 len = elems.length;
2458
2459 if ( outermost ) {
2460 outermostContext = context !== document && context;
2461 }
2462
2463 // Add elements passing elementMatchers directly to results
2464 // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
2465 // Support: IE<9, Safari
2466 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
2467 for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
2468 if ( byElement && elem ) {
2469 j = 0;
2470 while ( (matcher = elementMatchers[j++]) ) {
2471 if ( matcher( elem, context, xml ) ) {
2472 results.push( elem );
2473 break;
2474 }
2475 }
2476 if ( outermost ) {
2477 dirruns = dirrunsUnique;
2478 }
2479 }
2480
2481 // Track unmatched elements for set filters
2482 if ( bySet ) {
2483 // They will have gone through all possible matchers
2484 if ( (elem = !matcher && elem) ) {
2485 matchedCount--;
2486 }
2487
2488 // Lengthen the array for every element, matched or not
2489 if ( seed ) {
2490 unmatched.push( elem );
2491 }
2492 }
2493 }
2494
2495 // Apply set filters to unmatched elements
2496 matchedCount += i;
2497 if ( bySet && i !== matchedCount ) {
2498 j = 0;
2499 while ( (matcher = setMatchers[j++]) ) {
2500 matcher( unmatched, setMatched, context, xml );
2501 }
2502
2503 if ( seed ) {
2504 // Reintegrate element matches to eliminate the need for sorting
2505 if ( matchedCount > 0 ) {
2506 while ( i-- ) {
2507 if ( !(unmatched[i] || setMatched[i]) ) {
2508 setMatched[i] = pop.call( results );
2509 }
2510 }
2511 }
2512
2513 // Discard index placeholder values to get only actual matches
2514 setMatched = condense( setMatched );
2515 }
2516
2517 // Add matches to results
2518 push.apply( results, setMatched );
2519
2520 // Seedless set matches succeeding multiple successful matchers stipulate sorting
2521 if ( outermost && !seed && setMatched.length > 0 &&
2522 ( matchedCount + setMatchers.length ) > 1 ) {
2523
2524 Sizzle.uniqueSort( results );
2525 }
2526 }
2527
2528 // Override manipulation of globals by nested matchers
2529 if ( outermost ) {
2530 dirruns = dirrunsUnique;
2531 outermostContext = contextBackup;
2532 }
2533
2534 return unmatched;
2535 };
2536
2537 return bySet ?
2538 markFunction( superMatcher ) :
2539 superMatcher;
2540}
2541
2542compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
2543 var i,
2544 setMatchers = [],
2545 elementMatchers = [],
2546 cached = compilerCache[ selector + " " ];
2547
2548 if ( !cached ) {
2549 // Generate a function of recursive functions that can be used to check each element
2550 if ( !match ) {
2551 match = tokenize( selector );
2552 }
2553 i = match.length;
2554 while ( i-- ) {
2555 cached = matcherFromTokens( match[i] );
2556 if ( cached[ expando ] ) {
2557 setMatchers.push( cached );
2558 } else {
2559 elementMatchers.push( cached );
2560 }
2561 }
2562
2563 // Cache the compiled function
2564 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2565
2566 // Save selector and tokenization
2567 cached.selector = selector;
2568 }
2569 return cached;
2570};
2571
2572/**
2573 * A low-level selection function that works with Sizzle's compiled
2574 * selector functions
2575 * @param {String|Function} selector A selector or a pre-compiled
2576 * selector function built with Sizzle.compile
2577 * @param {Element} context
2578 * @param {Array} [results]
2579 * @param {Array} [seed] A set of elements to match against
2580 */
2581select = Sizzle.select = function( selector, context, results, seed ) {
2582 var i, tokens, token, type, find,
2583 compiled = typeof selector === "function" && selector,
2584 match = !seed && tokenize( (selector = compiled.selector || selector) );
2585
2586 results = results || [];
2587
2588 // Try to minimize operations if there is no seed and only one group
2589 if ( match.length === 1 ) {
2590
2591 // Take a shortcut and set the context if the root selector is an ID
2592 tokens = match[0] = match[0].slice( 0 );
2593 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
2594 support.getById && context.nodeType === 9 && documentIsHTML &&
2595 Expr.relative[ tokens[1].type ] ) {
2596
2597 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2598 if ( !context ) {
2599 return results;
2600
2601 // Precompiled matchers will still verify ancestry, so step up a level
2602 } else if ( compiled ) {
2603 context = context.parentNode;
2604 }
2605
2606 selector = selector.slice( tokens.shift().value.length );
2607 }
2608
2609 // Fetch a seed set for right-to-left matching
2610 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
2611 while ( i-- ) {
2612 token = tokens[i];
2613
2614 // Abort if we hit a combinator
2615 if ( Expr.relative[ (type = token.type) ] ) {
2616 break;
2617 }
2618 if ( (find = Expr.find[ type ]) ) {
2619 // Search, expanding context for leading sibling combinators
2620 if ( (seed = find(
2621 token.matches[0].replace( runescape, funescape ),
2622 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
2623 )) ) {
2624
2625 // If seed is empty or no tokens remain, we can return early
2626 tokens.splice( i, 1 );
2627 selector = seed.length && toSelector( tokens );
2628 if ( !selector ) {
2629 push.apply( results, seed );
2630 return results;
2631 }
2632
2633 break;
2634 }
2635 }
2636 }
2637 }
2638
2639 // Compile and execute a filtering function if one is not provided
2640 // Provide `match` to avoid retokenization if we modified the selector above
2641 ( compiled || compile( selector, match ) )(
2642 seed,
2643 context,
2644 !documentIsHTML,
2645 results,
2646 rsibling.test( selector ) && testContext( context.parentNode ) || context
2647 );
2648 return results;
2649};
2650
2651// One-time assignments
2652
2653// Sort stability
2654support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
2655
2656// Support: Chrome<14
2657// Always assume duplicates if they aren't passed to the comparison function
2658support.detectDuplicates = !!hasDuplicate;
2659
2660// Initialize against the default document
2661setDocument();
2662
2663// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2664// Detached nodes confoundingly follow *each other*
2665support.sortDetached = assert(function( div1 ) {
2666 // Should return 1, but returns 4 (following)
2667 return div1.compareDocumentPosition( document.createElement("div") ) & 1;
2668});
2669
2670// Support: IE<8
2671// Prevent attribute/property "interpolation"
2672// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2673if ( !assert(function( div ) {
2674 div.innerHTML = "<a href='#'></a>";
2675 return div.firstChild.getAttribute("href") === "#" ;
2676}) ) {
2677 addHandle( "type|href|height|width", function( elem, name, isXML ) {
2678 if ( !isXML ) {
2679 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2680 }
2681 });
2682}
2683
2684// Support: IE<9
2685// Use defaultValue in place of getAttribute("value")
2686if ( !support.attributes || !assert(function( div ) {
2687 div.innerHTML = "<input/>";
2688 div.firstChild.setAttribute( "value", "" );
2689 return div.firstChild.getAttribute( "value" ) === "";
2690}) ) {
2691 addHandle( "value", function( elem, name, isXML ) {
2692 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2693 return elem.defaultValue;
2694 }
2695 });
2696}
2697
2698// Support: IE<9
2699// Use getAttributeNode to fetch booleans when getAttribute lies
2700if ( !assert(function( div ) {
2701 return div.getAttribute("disabled") == null;
2702}) ) {
2703 addHandle( booleans, function( elem, name, isXML ) {
2704 var val;
2705 if ( !isXML ) {
2706 return elem[ name ] === true ? name.toLowerCase() :
2707 (val = elem.getAttributeNode( name )) && val.specified ?
2708 val.value :
2709 null;
2710 }
2711 });
2712}
2713
2714return Sizzle;
2715
2716})( window );
2717
2718
2719
2720jQuery.find = Sizzle;
2721jQuery.expr = Sizzle.selectors;
2722jQuery.expr[":"] = jQuery.expr.pseudos;
2723jQuery.unique = Sizzle.uniqueSort;
2724jQuery.text = Sizzle.getText;
2725jQuery.isXMLDoc = Sizzle.isXML;
2726jQuery.contains = Sizzle.contains;
2727
2728
2729
2730var rneedsContext = jQuery.expr.match.needsContext;
2731
2732var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
2733
2734
2735
2736var risSimple = /^.[^:#\[\.,]*$/;
2737
2738// Implement the identical functionality for filter and not
2739function winnow( elements, qualifier, not ) {
2740 if ( jQuery.isFunction( qualifier ) ) {
2741 return jQuery.grep( elements, function( elem, i ) {
2742 /* jshint -W018 */
2743 return !!qualifier.call( elem, i, elem ) !== not;
2744 });
2745
2746 }
2747
2748 if ( qualifier.nodeType ) {
2749 return jQuery.grep( elements, function( elem ) {
2750 return ( elem === qualifier ) !== not;
2751 });
2752
2753 }
2754
2755 if ( typeof qualifier === "string" ) {
2756 if ( risSimple.test( qualifier ) ) {
2757 return jQuery.filter( qualifier, elements, not );
2758 }
2759
2760 qualifier = jQuery.filter( qualifier, elements );
2761 }
2762
2763 return jQuery.grep( elements, function( elem ) {
2764 return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
2765 });
2766}
2767
2768jQuery.filter = function( expr, elems, not ) {
2769 var elem = elems[ 0 ];
2770
2771 if ( not ) {
2772 expr = ":not(" + expr + ")";
2773 }
2774
2775 return elems.length === 1 && elem.nodeType === 1 ?
2776 jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
2777 jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
2778 return elem.nodeType === 1;
2779 }));
2780};
2781
2782jQuery.fn.extend({
2783 find: function( selector ) {
2784 var i,
2785 ret = [],
2786 self = this,
2787 len = self.length;
2788
2789 if ( typeof selector !== "string" ) {
2790 return this.pushStack( jQuery( selector ).filter(function() {
2791 for ( i = 0; i < len; i++ ) {
2792 if ( jQuery.contains( self[ i ], this ) ) {
2793 return true;
2794 }
2795 }
2796 }) );
2797 }
2798
2799 for ( i = 0; i < len; i++ ) {
2800 jQuery.find( selector, self[ i ], ret );
2801 }
2802
2803 // Needed because $( selector, context ) becomes $( context ).find( selector )
2804 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
2805 ret.selector = this.selector ? this.selector + " " + selector : selector;
2806 return ret;
2807 },
2808 filter: function( selector ) {
2809 return this.pushStack( winnow(this, selector || [], false) );
2810 },
2811 not: function( selector ) {
2812 return this.pushStack( winnow(this, selector || [], true) );
2813 },
2814 is: function( selector ) {
2815 return !!winnow(
2816 this,
2817
2818 // If this is a positional/relative selector, check membership in the returned set
2819 // so $("p:first").is("p:last") won't return true for a doc with two "p".
2820 typeof selector === "string" && rneedsContext.test( selector ) ?
2821 jQuery( selector ) :
2822 selector || [],
2823 false
2824 ).length;
2825 }
2826});
2827
2828
2829// Initialize a jQuery object
2830
2831
2832// A central reference to the root jQuery(document)
2833var rootjQuery,
2834
2835 // Use the correct document accordingly with window argument (sandbox)
2836 document = window.document,
2837
2838 // A simple way to check for HTML strings
2839 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
2840 // Strict HTML recognition (#11290: must start with <)
2841 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
2842
2843 init = jQuery.fn.init = function( selector, context ) {
2844 var match, elem;
2845
2846 // HANDLE: $(""), $(null), $(undefined), $(false)
2847 if ( !selector ) {
2848 return this;
2849 }
2850
2851 // Handle HTML strings
2852 if ( typeof selector === "string" ) {
2853 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
2854 // Assume that strings that start and end with <> are HTML and skip the regex check
2855 match = [ null, selector, null ];
2856
2857 } else {
2858 match = rquickExpr.exec( selector );
2859 }
2860
2861 // Match html or make sure no context is specified for #id
2862 if ( match && (match[1] || !context) ) {
2863
2864 // HANDLE: $(html) -> $(array)
2865 if ( match[1] ) {
2866 context = context instanceof jQuery ? context[0] : context;
2867
2868 // scripts is true for back-compat
2869 // Intentionally let the error be thrown if parseHTML is not present
2870 jQuery.merge( this, jQuery.parseHTML(
2871 match[1],
2872 context && context.nodeType ? context.ownerDocument || context : document,
2873 true
2874 ) );
2875
2876 // HANDLE: $(html, props)
2877 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
2878 for ( match in context ) {
2879 // Properties of context are called as methods if possible
2880 if ( jQuery.isFunction( this[ match ] ) ) {
2881 this[ match ]( context[ match ] );
2882
2883 // ...and otherwise set as attributes
2884 } else {
2885 this.attr( match, context[ match ] );
2886 }
2887 }
2888 }
2889
2890 return this;
2891
2892 // HANDLE: $(#id)
2893 } else {
2894 elem = document.getElementById( match[2] );
2895
2896 // Check parentNode to catch when Blackberry 4.6 returns
2897 // nodes that are no longer in the document #6963
2898 if ( elem && elem.parentNode ) {
2899 // Handle the case where IE and Opera return items
2900 // by name instead of ID
2901 if ( elem.id !== match[2] ) {
2902 return rootjQuery.find( selector );
2903 }
2904
2905 // Otherwise, we inject the element directly into the jQuery object
2906 this.length = 1;
2907 this[0] = elem;
2908 }
2909
2910 this.context = document;
2911 this.selector = selector;
2912 return this;
2913 }
2914
2915 // HANDLE: $(expr, $(...))
2916 } else if ( !context || context.jquery ) {
2917 return ( context || rootjQuery ).find( selector );
2918
2919 // HANDLE: $(expr, context)
2920 // (which is just equivalent to: $(context).find(expr)
2921 } else {
2922 return this.constructor( context ).find( selector );
2923 }
2924
2925 // HANDLE: $(DOMElement)
2926 } else if ( selector.nodeType ) {
2927 this.context = this[0] = selector;
2928 this.length = 1;
2929 return this;
2930
2931 // HANDLE: $(function)
2932 // Shortcut for document ready
2933 } else if ( jQuery.isFunction( selector ) ) {
2934 return typeof rootjQuery.ready !== "undefined" ?
2935 rootjQuery.ready( selector ) :
2936 // Execute immediately if ready is not present
2937 selector( jQuery );
2938 }
2939
2940 if ( selector.selector !== undefined ) {
2941 this.selector = selector.selector;
2942 this.context = selector.context;
2943 }
2944
2945 return jQuery.makeArray( selector, this );
2946 };
2947
2948// Give the init function the jQuery prototype for later instantiation
2949init.prototype = jQuery.fn;
2950
2951// Initialize central reference
2952rootjQuery = jQuery( document );
2953
2954
2955var rparentsprev = /^(?:parents|prev(?:Until|All))/,
2956 // methods guaranteed to produce a unique set when starting from a unique set
2957 guaranteedUnique = {
2958 children: true,
2959 contents: true,
2960 next: true,
2961 prev: true
2962 };
2963
2964jQuery.extend({
2965 dir: function( elem, dir, until ) {
2966 var matched = [],
2967 cur = elem[ dir ];
2968
2969 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
2970 if ( cur.nodeType === 1 ) {
2971 matched.push( cur );
2972 }
2973 cur = cur[dir];
2974 }
2975 return matched;
2976 },
2977
2978 sibling: function( n, elem ) {
2979 var r = [];
2980
2981 for ( ; n; n = n.nextSibling ) {
2982 if ( n.nodeType === 1 && n !== elem ) {
2983 r.push( n );
2984 }
2985 }
2986
2987 return r;
2988 }
2989});
2990
2991jQuery.fn.extend({
2992 has: function( target ) {
2993 var i,
2994 targets = jQuery( target, this ),
2995 len = targets.length;
2996
2997 return this.filter(function() {
2998 for ( i = 0; i < len; i++ ) {
2999 if ( jQuery.contains( this, targets[i] ) ) {
3000 return true;
3001 }
3002 }
3003 });
3004 },
3005
3006 closest: function( selectors, context ) {
3007 var cur,
3008 i = 0,
3009 l = this.length,
3010 matched = [],
3011 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
3012 jQuery( selectors, context || this.context ) :
3013 0;
3014
3015 for ( ; i < l; i++ ) {
3016 for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
3017 // Always skip document fragments
3018 if ( cur.nodeType < 11 && (pos ?
3019 pos.index(cur) > -1 :
3020
3021 // Don't pass non-elements to Sizzle
3022 cur.nodeType === 1 &&
3023 jQuery.find.matchesSelector(cur, selectors)) ) {
3024
3025 matched.push( cur );
3026 break;
3027 }
3028 }
3029 }
3030
3031 return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
3032 },
3033
3034 // Determine the position of an element within
3035 // the matched set of elements
3036 index: function( elem ) {
3037
3038 // No argument, return index in parent
3039 if ( !elem ) {
3040 return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
3041 }
3042
3043 // index in selector
3044 if ( typeof elem === "string" ) {
3045 return jQuery.inArray( this[0], jQuery( elem ) );
3046 }
3047
3048 // Locate the position of the desired element
3049 return jQuery.inArray(
3050 // If it receives a jQuery object, the first element is used
3051 elem.jquery ? elem[0] : elem, this );
3052 },
3053
3054 add: function( selector, context ) {
3055 return this.pushStack(
3056 jQuery.unique(
3057 jQuery.merge( this.get(), jQuery( selector, context ) )
3058 )
3059 );
3060 },
3061
3062 addBack: function( selector ) {
3063 return this.add( selector == null ?
3064 this.prevObject : this.prevObject.filter(selector)
3065 );
3066 }
3067});
3068
3069function sibling( cur, dir ) {
3070 do {
3071 cur = cur[ dir ];
3072 } while ( cur && cur.nodeType !== 1 );
3073
3074 return cur;
3075}
3076
3077jQuery.each({
3078 parent: function( elem ) {
3079 var parent = elem.parentNode;
3080 return parent && parent.nodeType !== 11 ? parent : null;
3081 },
3082 parents: function( elem ) {
3083 return jQuery.dir( elem, "parentNode" );
3084 },
3085 parentsUntil: function( elem, i, until ) {
3086 return jQuery.dir( elem, "parentNode", until );
3087 },
3088 next: function( elem ) {
3089 return sibling( elem, "nextSibling" );
3090 },
3091 prev: function( elem ) {
3092 return sibling( elem, "previousSibling" );
3093 },
3094 nextAll: function( elem ) {
3095 return jQuery.dir( elem, "nextSibling" );
3096 },
3097 prevAll: function( elem ) {
3098 return jQuery.dir( elem, "previousSibling" );
3099 },
3100 nextUntil: function( elem, i, until ) {
3101 return jQuery.dir( elem, "nextSibling", until );
3102 },
3103 prevUntil: function( elem, i, until ) {
3104 return jQuery.dir( elem, "previousSibling", until );
3105 },
3106 siblings: function( elem ) {
3107 return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
3108 },
3109 children: function( elem ) {
3110 return jQuery.sibling( elem.firstChild );
3111 },
3112 contents: function( elem ) {
3113 return jQuery.nodeName( elem, "iframe" ) ?
3114 elem.contentDocument || elem.contentWindow.document :
3115 jQuery.merge( [], elem.childNodes );
3116 }
3117}, function( name, fn ) {
3118 jQuery.fn[ name ] = function( until, selector ) {
3119 var ret = jQuery.map( this, fn, until );
3120
3121 if ( name.slice( -5 ) !== "Until" ) {
3122 selector = until;
3123 }
3124
3125 if ( selector && typeof selector === "string" ) {
3126 ret = jQuery.filter( selector, ret );
3127 }
3128
3129 if ( this.length > 1 ) {
3130 // Remove duplicates
3131 if ( !guaranteedUnique[ name ] ) {
3132 ret = jQuery.unique( ret );
3133 }
3134
3135 // Reverse order for parents* and prev-derivatives
3136 if ( rparentsprev.test( name ) ) {
3137 ret = ret.reverse();
3138 }
3139 }
3140
3141 return this.pushStack( ret );
3142 };
3143});
3144var rnotwhite = (/\S+/g);
3145
3146
3147
3148// String to Object options format cache
3149var optionsCache = {};
3150
3151// Convert String-formatted options into Object-formatted ones and store in cache
3152function createOptions( options ) {
3153 var object = optionsCache[ options ] = {};
3154 jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
3155 object[ flag ] = true;
3156 });
3157 return object;
3158}
3159
3160/*
3161 * Create a callback list using the following parameters:
3162 *
3163 * options: an optional list of space-separated options that will change how
3164 * the callback list behaves or a more traditional option object
3165 *
3166 * By default a callback list will act like an event callback list and can be
3167 * "fired" multiple times.
3168 *
3169 * Possible options:
3170 *
3171 * once: will ensure the callback list can only be fired once (like a Deferred)
3172 *
3173 * memory: will keep track of previous values and will call any callback added
3174 * after the list has been fired right away with the latest "memorized"
3175 * values (like a Deferred)
3176 *
3177 * unique: will ensure a callback can only be added once (no duplicate in the list)
3178 *
3179 * stopOnFalse: interrupt callings when a callback returns false
3180 *
3181 */
3182jQuery.Callbacks = function( options ) {
3183
3184 // Convert options from String-formatted to Object-formatted if needed
3185 // (we check in cache first)
3186 options = typeof options === "string" ?
3187 ( optionsCache[ options ] || createOptions( options ) ) :
3188 jQuery.extend( {}, options );
3189
3190 var // Flag to know if list is currently firing
3191 firing,
3192 // Last fire value (for non-forgettable lists)
3193 memory,
3194 // Flag to know if list was already fired
3195 fired,
3196 // End of the loop when firing
3197 firingLength,
3198 // Index of currently firing callback (modified by remove if needed)
3199 firingIndex,
3200 // First callback to fire (used internally by add and fireWith)
3201 firingStart,
3202 // Actual callback list
3203 list = [],
3204 // Stack of fire calls for repeatable lists
3205 stack = !options.once && [],
3206 // Fire callbacks
3207 fire = function( data ) {
3208 memory = options.memory && data;
3209 fired = true;
3210 firingIndex = firingStart || 0;
3211 firingStart = 0;
3212 firingLength = list.length;
3213 firing = true;
3214 for ( ; list && firingIndex < firingLength; firingIndex++ ) {
3215 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
3216 memory = false; // To prevent further calls using add
3217 break;
3218 }
3219 }
3220 firing = false;
3221 if ( list ) {
3222 if ( stack ) {
3223 if ( stack.length ) {
3224 fire( stack.shift() );
3225 }
3226 } else if ( memory ) {
3227 list = [];
3228 } else {
3229 self.disable();
3230 }
3231 }
3232 },
3233 // Actual Callbacks object
3234 self = {
3235 // Add a callback or a collection of callbacks to the list
3236 add: function() {
3237 if ( list ) {
3238 // First, we save the current length
3239 var start = list.length;
3240 (function add( args ) {
3241 jQuery.each( args, function( _, arg ) {
3242 var type = jQuery.type( arg );
3243 if ( type === "function" ) {
3244 if ( !options.unique || !self.has( arg ) ) {
3245 list.push( arg );
3246 }
3247 } else if ( arg && arg.length && type !== "string" ) {
3248 // Inspect recursively
3249 add( arg );
3250 }
3251 });
3252 })( arguments );
3253 // Do we need to add the callbacks to the
3254 // current firing batch?
3255 if ( firing ) {
3256 firingLength = list.length;
3257 // With memory, if we're not firing then
3258 // we should call right away
3259 } else if ( memory ) {
3260 firingStart = start;
3261 fire( memory );
3262 }
3263 }
3264 return this;
3265 },
3266 // Remove a callback from the list
3267 remove: function() {
3268 if ( list ) {
3269 jQuery.each( arguments, function( _, arg ) {
3270 var index;
3271 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3272 list.splice( index, 1 );
3273 // Handle firing indexes
3274 if ( firing ) {
3275 if ( index <= firingLength ) {
3276 firingLength--;
3277 }
3278 if ( index <= firingIndex ) {
3279 firingIndex--;
3280 }
3281 }
3282 }
3283 });
3284 }
3285 return this;
3286 },
3287 // Check if a given callback is in the list.
3288 // If no argument is given, return whether or not list has callbacks attached.
3289 has: function( fn ) {
3290 return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
3291 },
3292 // Remove all callbacks from the list
3293 empty: function() {
3294 list = [];
3295 firingLength = 0;
3296 return this;
3297 },
3298 // Have the list do nothing anymore
3299 disable: function() {
3300 list = stack = memory = undefined;
3301 return this;
3302 },
3303 // Is it disabled?
3304 disabled: function() {
3305 return !list;
3306 },
3307 // Lock the list in its current state
3308 lock: function() {
3309 stack = undefined;
3310 if ( !memory ) {
3311 self.disable();
3312 }
3313 return this;
3314 },
3315 // Is it locked?
3316 locked: function() {
3317 return !stack;
3318 },
3319 // Call all callbacks with the given context and arguments
3320 fireWith: function( context, args ) {
3321 if ( list && ( !fired || stack ) ) {
3322 args = args || [];
3323 args = [ context, args.slice ? args.slice() : args ];
3324 if ( firing ) {
3325 stack.push( args );
3326 } else {
3327 fire( args );
3328 }
3329 }
3330 return this;
3331 },
3332 // Call all the callbacks with the given arguments
3333 fire: function() {
3334 self.fireWith( this, arguments );
3335 return this;
3336 },
3337 // To know if the callbacks have already been called at least once
3338 fired: function() {
3339 return !!fired;
3340 }
3341 };
3342
3343 return self;
3344};
3345
3346
3347jQuery.extend({
3348
3349 Deferred: function( func ) {
3350 var tuples = [
3351 // action, add listener, listener list, final state
3352 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
3353 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
3354 [ "notify", "progress", jQuery.Callbacks("memory") ]
3355 ],
3356 state = "pending",
3357 promise = {
3358 state: function() {
3359 return state;
3360 },
3361 always: function() {
3362 deferred.done( arguments ).fail( arguments );
3363 return this;
3364 },
3365 then: function( /* fnDone, fnFail, fnProgress */ ) {
3366 var fns = arguments;
3367 return jQuery.Deferred(function( newDefer ) {
3368 jQuery.each( tuples, function( i, tuple ) {
3369 var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
3370 // deferred[ done | fail | progress ] for forwarding actions to newDefer
3371 deferred[ tuple[1] ](function() {
3372 var returned = fn && fn.apply( this, arguments );
3373 if ( returned && jQuery.isFunction( returned.promise ) ) {
3374 returned.promise()
3375 .done( newDefer.resolve )
3376 .fail( newDefer.reject )
3377 .progress( newDefer.notify );
3378 } else {
3379 newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
3380 }
3381 });
3382 });
3383 fns = null;
3384 }).promise();
3385 },
3386 // Get a promise for this deferred
3387 // If obj is provided, the promise aspect is added to the object
3388 promise: function( obj ) {
3389 return obj != null ? jQuery.extend( obj, promise ) : promise;
3390 }
3391 },
3392 deferred = {};
3393
3394 // Keep pipe for back-compat
3395 promise.pipe = promise.then;
3396
3397 // Add list-specific methods
3398 jQuery.each( tuples, function( i, tuple ) {
3399 var list = tuple[ 2 ],
3400 stateString = tuple[ 3 ];
3401
3402 // promise[ done | fail | progress ] = list.add
3403 promise[ tuple[1] ] = list.add;
3404
3405 // Handle state
3406 if ( stateString ) {
3407 list.add(function() {
3408 // state = [ resolved | rejected ]
3409 state = stateString;
3410
3411 // [ reject_list | resolve_list ].disable; progress_list.lock
3412 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
3413 }
3414
3415 // deferred[ resolve | reject | notify ]
3416 deferred[ tuple[0] ] = function() {
3417 deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
3418 return this;
3419 };
3420 deferred[ tuple[0] + "With" ] = list.fireWith;
3421 });
3422
3423 // Make the deferred a promise
3424 promise.promise( deferred );
3425
3426 // Call given func if any
3427 if ( func ) {
3428 func.call( deferred, deferred );
3429 }
3430
3431 // All done!
3432 return deferred;
3433 },
3434
3435 // Deferred helper
3436 when: function( subordinate /* , ..., subordinateN */ ) {
3437 var i = 0,
3438 resolveValues = slice.call( arguments ),
3439 length = resolveValues.length,
3440
3441 // the count of uncompleted subordinates
3442 remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
3443
3444 // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
3445 deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
3446
3447 // Update function for both resolve and progress values
3448 updateFunc = function( i, contexts, values ) {
3449 return function( value ) {
3450 contexts[ i ] = this;
3451 values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3452 if ( values === progressValues ) {
3453 deferred.notifyWith( contexts, values );
3454
3455 } else if ( !(--remaining) ) {
3456 deferred.resolveWith( contexts, values );
3457 }
3458 };
3459 },
3460
3461 progressValues, progressContexts, resolveContexts;
3462
3463 // add listeners to Deferred subordinates; treat others as resolved
3464 if ( length > 1 ) {
3465 progressValues = new Array( length );
3466 progressContexts = new Array( length );
3467 resolveContexts = new Array( length );
3468 for ( ; i < length; i++ ) {
3469 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
3470 resolveValues[ i ].promise()
3471 .done( updateFunc( i, resolveContexts, resolveValues ) )
3472 .fail( deferred.reject )
3473 .progress( updateFunc( i, progressContexts, progressValues ) );
3474 } else {
3475 --remaining;
3476 }
3477 }
3478 }
3479
3480 // if we're not waiting on anything, resolve the master
3481 if ( !remaining ) {
3482 deferred.resolveWith( resolveContexts, resolveValues );
3483 }
3484
3485 return deferred.promise();
3486 }
3487});
3488
3489
3490// The deferred used on DOM ready
3491var readyList;
3492
3493jQuery.fn.ready = function( fn ) {
3494 // Add the callback
3495 jQuery.ready.promise().done( fn );
3496
3497 return this;
3498};
3499
3500jQuery.extend({
3501 // Is the DOM ready to be used? Set to true once it occurs.
3502 isReady: false,
3503
3504 // A counter to track how many items to wait for before
3505 // the ready event fires. See #6781
3506 readyWait: 1,
3507
3508 // Hold (or release) the ready event
3509 holdReady: function( hold ) {
3510 if ( hold ) {
3511 jQuery.readyWait++;
3512 } else {
3513 jQuery.ready( true );
3514 }
3515 },
3516
3517 // Handle when the DOM is ready
3518 ready: function( wait ) {
3519
3520 // Abort if there are pending holds or we're already ready
3521 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
3522 return;
3523 }
3524
3525 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
3526 if ( !document.body ) {
3527 return setTimeout( jQuery.ready );
3528 }
3529
3530 // Remember that the DOM is ready
3531 jQuery.isReady = true;
3532
3533 // If a normal DOM Ready event fired, decrement, and wait if need be
3534 if ( wait !== true && --jQuery.readyWait > 0 ) {
3535 return;
3536 }
3537
3538 // If there are functions bound, to execute
3539 readyList.resolveWith( document, [ jQuery ] );
3540
3541 // Trigger any bound ready events
3542 if ( jQuery.fn.triggerHandler ) {
3543 jQuery( document ).triggerHandler( "ready" );
3544 jQuery( document ).off( "ready" );
3545 }
3546 }
3547});
3548
3549/**
3550 * Clean-up method for dom ready events
3551 */
3552function detach() {
3553 if ( document.addEventListener ) {
3554 document.removeEventListener( "DOMContentLoaded", completed, false );
3555 window.removeEventListener( "load", completed, false );
3556
3557 } else {
3558 document.detachEvent( "onreadystatechange", completed );
3559 window.detachEvent( "onload", completed );
3560 }
3561}
3562
3563/**
3564 * The ready event handler and self cleanup method
3565 */
3566function completed() {
3567 // readyState === "complete" is good enough for us to call the dom ready in oldIE
3568 if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
3569 detach();
3570 jQuery.ready();
3571 }
3572}
3573
3574jQuery.ready.promise = function( obj ) {
3575 if ( !readyList ) {
3576
3577 readyList = jQuery.Deferred();
3578
3579 // Catch cases where $(document).ready() is called after the browser event has already occurred.
3580 // we once tried to use readyState "interactive" here, but it caused issues like the one
3581 // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
3582 if ( document.readyState === "complete" ) {
3583 // Handle it asynchronously to allow scripts the opportunity to delay ready
3584 setTimeout( jQuery.ready );
3585
3586 // Standards-based browsers support DOMContentLoaded
3587 } else if ( document.addEventListener ) {
3588 // Use the handy event callback
3589 document.addEventListener( "DOMContentLoaded", completed, false );
3590
3591 // A fallback to window.onload, that will always work
3592 window.addEventListener( "load", completed, false );
3593
3594 // If IE event model is used
3595 } else {
3596 // Ensure firing before onload, maybe late but safe also for iframes
3597 document.attachEvent( "onreadystatechange", completed );
3598
3599 // A fallback to window.onload, that will always work
3600 window.attachEvent( "onload", completed );
3601
3602 // If IE and not a frame
3603 // continually check to see if the document is ready
3604 var top = false;
3605
3606 try {
3607 top = window.frameElement == null && document.documentElement;
3608 } catch(e) {}
3609
3610 if ( top && top.doScroll ) {
3611 (function doScrollCheck() {
3612 if ( !jQuery.isReady ) {
3613
3614 try {
3615 // Use the trick by Diego Perini
3616 // http://javascript.nwbox.com/IEContentLoaded/
3617 top.doScroll("left");
3618 } catch(e) {
3619 return setTimeout( doScrollCheck, 50 );
3620 }
3621
3622 // detach all dom ready events
3623 detach();
3624
3625 // and execute any waiting functions
3626 jQuery.ready();
3627 }
3628 })();
3629 }
3630 }
3631 }
3632 return readyList.promise( obj );
3633};
3634
3635
3636var strundefined = typeof undefined;
3637
3638
3639
3640// Support: IE<9
3641// Iteration over object's inherited properties before its own
3642var i;
3643for ( i in jQuery( support ) ) {
3644 break;
3645}
3646support.ownLast = i !== "0";
3647
3648// Note: most support tests are defined in their respective modules.
3649// false until the test is run
3650support.inlineBlockNeedsLayout = false;
3651
3652// Execute ASAP in case we need to set body.style.zoom
3653jQuery(function() {
3654 // Minified: var a,b,c,d
3655 var val, div, body, container;
3656
3657 body = document.getElementsByTagName( "body" )[ 0 ];
3658 if ( !body || !body.style ) {
3659 // Return for frameset docs that don't have a body
3660 return;
3661 }
3662
3663 // Setup
3664 div = document.createElement( "div" );
3665 container = document.createElement( "div" );
3666 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
3667 body.appendChild( container ).appendChild( div );
3668
3669 if ( typeof div.style.zoom !== strundefined ) {
3670 // Support: IE<8
3671 // Check if natively block-level elements act like inline-block
3672 // elements when setting their display to 'inline' and giving
3673 // them layout
3674 div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
3675
3676 support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
3677 if ( val ) {
3678 // Prevent IE 6 from affecting layout for positioned elements #11048
3679 // Prevent IE from shrinking the body in IE 7 mode #12869
3680 // Support: IE<8
3681 body.style.zoom = 1;
3682 }
3683 }
3684
3685 body.removeChild( container );
3686});
3687
3688
3689
3690
3691(function() {
3692 var div = document.createElement( "div" );
3693
3694 // Execute the test only if not already executed in another module.
3695 if (support.deleteExpando == null) {
3696 // Support: IE<9
3697 support.deleteExpando = true;
3698 try {
3699 delete div.test;
3700 } catch( e ) {
3701 support.deleteExpando = false;
3702 }
3703 }
3704
3705 // Null elements to avoid leaks in IE.
3706 div = null;
3707})();
3708
3709
3710/**
3711 * Determines whether an object can have data
3712 */
3713jQuery.acceptData = function( elem ) {
3714 var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
3715 nodeType = +elem.nodeType || 1;
3716
3717 // Do not set data on non-element DOM nodes because it will not be cleared (#8335).
3718 return nodeType !== 1 && nodeType !== 9 ?
3719 false :
3720
3721 // Nodes accept data unless otherwise specified; rejection can be conditional
3722 !noData || noData !== true && elem.getAttribute("classid") === noData;
3723};
3724
3725
3726var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
3727 rmultiDash = /([A-Z])/g;
3728
3729function dataAttr( elem, key, data ) {
3730 // If nothing was found internally, try to fetch any
3731 // data from the HTML5 data-* attribute
3732 if ( data === undefined && elem.nodeType === 1 ) {
3733
3734 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
3735
3736 data = elem.getAttribute( name );
3737
3738 if ( typeof data === "string" ) {
3739 try {
3740 data = data === "true" ? true :
3741 data === "false" ? false :
3742 data === "null" ? null :
3743 // Only convert to a number if it doesn't change the string
3744 +data + "" === data ? +data :
3745 rbrace.test( data ) ? jQuery.parseJSON( data ) :
3746 data;
3747 } catch( e ) {}
3748
3749 // Make sure we set the data so it isn't changed later
3750 jQuery.data( elem, key, data );
3751
3752 } else {
3753 data = undefined;
3754 }
3755 }
3756
3757 return data;
3758}
3759
3760// checks a cache object for emptiness
3761function isEmptyDataObject( obj ) {
3762 var name;
3763 for ( name in obj ) {
3764
3765 // if the public data object is empty, the private is still empty
3766 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
3767 continue;
3768 }
3769 if ( name !== "toJSON" ) {
3770 return false;
3771 }
3772 }
3773
3774 return true;
3775}
3776
3777function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
3778 if ( !jQuery.acceptData( elem ) ) {
3779 return;
3780 }
3781
3782 var ret, thisCache,
3783 internalKey = jQuery.expando,
3784
3785 // We have to handle DOM nodes and JS objects differently because IE6-7
3786 // can't GC object references properly across the DOM-JS boundary
3787 isNode = elem.nodeType,
3788
3789 // Only DOM nodes need the global jQuery cache; JS object data is
3790 // attached directly to the object so GC can occur automatically
3791 cache = isNode ? jQuery.cache : elem,
3792
3793 // Only defining an ID for JS objects if its cache already exists allows
3794 // the code to shortcut on the same path as a DOM node with no cache
3795 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
3796
3797 // Avoid doing any more work than we need to when trying to get data on an
3798 // object that has no data at all
3799 if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
3800 return;
3801 }
3802
3803 if ( !id ) {
3804 // Only DOM nodes need a new unique ID for each element since their data
3805 // ends up in the global cache
3806 if ( isNode ) {
3807 id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
3808 } else {
3809 id = internalKey;
3810 }
3811 }
3812
3813 if ( !cache[ id ] ) {
3814 // Avoid exposing jQuery metadata on plain JS objects when the object
3815 // is serialized using JSON.stringify
3816 cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
3817 }
3818
3819 // An object can be passed to jQuery.data instead of a key/value pair; this gets
3820 // shallow copied over onto the existing cache
3821 if ( typeof name === "object" || typeof name === "function" ) {
3822 if ( pvt ) {
3823 cache[ id ] = jQuery.extend( cache[ id ], name );
3824 } else {
3825 cache[ id ].data = jQuery.extend( cache[ id ].data, name );
3826 }
3827 }
3828
3829 thisCache = cache[ id ];
3830
3831 // jQuery data() is stored in a separate object inside the object's internal data
3832 // cache in order to avoid key collisions between internal data and user-defined
3833 // data.
3834 if ( !pvt ) {
3835 if ( !thisCache.data ) {
3836 thisCache.data = {};
3837 }
3838
3839 thisCache = thisCache.data;
3840 }
3841
3842 if ( data !== undefined ) {
3843 thisCache[ jQuery.camelCase( name ) ] = data;
3844 }
3845
3846 // Check for both converted-to-camel and non-converted data property names
3847 // If a data property was specified
3848 if ( typeof name === "string" ) {
3849
3850 // First Try to find as-is property data
3851 ret = thisCache[ name ];
3852
3853 // Test for null|undefined property data
3854 if ( ret == null ) {
3855
3856 // Try to find the camelCased property
3857 ret = thisCache[ jQuery.camelCase( name ) ];
3858 }
3859 } else {
3860 ret = thisCache;
3861 }
3862
3863 return ret;
3864}
3865
3866function internalRemoveData( elem, name, pvt ) {
3867 if ( !jQuery.acceptData( elem ) ) {
3868 return;
3869 }
3870
3871 var thisCache, i,
3872 isNode = elem.nodeType,
3873
3874 // See jQuery.data for more information
3875 cache = isNode ? jQuery.cache : elem,
3876 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
3877
3878 // If there is already no cache entry for this object, there is no
3879 // purpose in continuing
3880 if ( !cache[ id ] ) {
3881 return;
3882 }
3883
3884 if ( name ) {
3885
3886 thisCache = pvt ? cache[ id ] : cache[ id ].data;
3887
3888 if ( thisCache ) {
3889
3890 // Support array or space separated string names for data keys
3891 if ( !jQuery.isArray( name ) ) {
3892
3893 // try the string as a key before any manipulation
3894 if ( name in thisCache ) {
3895 name = [ name ];
3896 } else {
3897
3898 // split the camel cased version by spaces unless a key with the spaces exists
3899 name = jQuery.camelCase( name );
3900 if ( name in thisCache ) {
3901 name = [ name ];
3902 } else {
3903 name = name.split(" ");
3904 }
3905 }
3906 } else {
3907 // If "name" is an array of keys...
3908 // When data is initially created, via ("key", "val") signature,
3909 // keys will be converted to camelCase.
3910 // Since there is no way to tell _how_ a key was added, remove
3911 // both plain key and camelCase key. #12786
3912 // This will only penalize the array argument path.
3913 name = name.concat( jQuery.map( name, jQuery.camelCase ) );
3914 }
3915
3916 i = name.length;
3917 while ( i-- ) {
3918 delete thisCache[ name[i] ];
3919 }
3920
3921 // If there is no data left in the cache, we want to continue
3922 // and let the cache object itself get destroyed
3923 if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
3924 return;
3925 }
3926 }
3927 }
3928
3929 // See jQuery.data for more information
3930 if ( !pvt ) {
3931 delete cache[ id ].data;
3932
3933 // Don't destroy the parent cache unless the internal data object
3934 // had been the only thing left in it
3935 if ( !isEmptyDataObject( cache[ id ] ) ) {
3936 return;
3937 }
3938 }
3939
3940 // Destroy the cache
3941 if ( isNode ) {
3942 jQuery.cleanData( [ elem ], true );
3943
3944 // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
3945 /* jshint eqeqeq: false */
3946 } else if ( support.deleteExpando || cache != cache.window ) {
3947 /* jshint eqeqeq: true */
3948 delete cache[ id ];
3949
3950 // When all else fails, null
3951 } else {
3952 cache[ id ] = null;
3953 }
3954}
3955
3956jQuery.extend({
3957 cache: {},
3958
3959 // The following elements (space-suffixed to avoid Object.prototype collisions)
3960 // throw uncatchable exceptions if you attempt to set expando properties
3961 noData: {
3962 "applet ": true,
3963 "embed ": true,
3964 // ...but Flash objects (which have this classid) *can* handle expandos
3965 "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
3966 },
3967
3968 hasData: function( elem ) {
3969 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
3970 return !!elem && !isEmptyDataObject( elem );
3971 },
3972
3973 data: function( elem, name, data ) {
3974 return internalData( elem, name, data );
3975 },
3976
3977 removeData: function( elem, name ) {
3978 return internalRemoveData( elem, name );
3979 },
3980
3981 // For internal use only.
3982 _data: function( elem, name, data ) {
3983 return internalData( elem, name, data, true );
3984 },
3985
3986 _removeData: function( elem, name ) {
3987 return internalRemoveData( elem, name, true );
3988 }
3989});
3990
3991jQuery.fn.extend({
3992 data: function( key, value ) {
3993 var i, name, data,
3994 elem = this[0],
3995 attrs = elem && elem.attributes;
3996
3997 // Special expections of .data basically thwart jQuery.access,
3998 // so implement the relevant behavior ourselves
3999
4000 // Gets all values
4001 if ( key === undefined ) {
4002 if ( this.length ) {
4003 data = jQuery.data( elem );
4004
4005 if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
4006 i = attrs.length;
4007 while ( i-- ) {
4008
4009 // Support: IE11+
4010 // The attrs elements can be null (#14894)
4011 if ( attrs[ i ] ) {
4012 name = attrs[ i ].name;
4013 if ( name.indexOf( "data-" ) === 0 ) {
4014 name = jQuery.camelCase( name.slice(5) );
4015 dataAttr( elem, name, data[ name ] );
4016 }
4017 }
4018 }
4019 jQuery._data( elem, "parsedAttrs", true );
4020 }
4021 }
4022
4023 return data;
4024 }
4025
4026 // Sets multiple values
4027 if ( typeof key === "object" ) {
4028 return this.each(function() {
4029 jQuery.data( this, key );
4030 });
4031 }
4032
4033 return arguments.length > 1 ?
4034
4035 // Sets one value
4036 this.each(function() {
4037 jQuery.data( this, key, value );
4038 }) :
4039
4040 // Gets one value
4041 // Try to fetch any internally stored data first
4042 elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
4043 },
4044
4045 removeData: function( key ) {
4046 return this.each(function() {
4047 jQuery.removeData( this, key );
4048 });
4049 }
4050});
4051
4052
4053jQuery.extend({
4054 queue: function( elem, type, data ) {
4055 var queue;
4056
4057 if ( elem ) {
4058 type = ( type || "fx" ) + "queue";
4059 queue = jQuery._data( elem, type );
4060
4061 // Speed up dequeue by getting out quickly if this is just a lookup
4062 if ( data ) {
4063 if ( !queue || jQuery.isArray(data) ) {
4064 queue = jQuery._data( elem, type, jQuery.makeArray(data) );
4065 } else {
4066 queue.push( data );
4067 }
4068 }
4069 return queue || [];
4070 }
4071 },
4072
4073 dequeue: function( elem, type ) {
4074 type = type || "fx";
4075
4076 var queue = jQuery.queue( elem, type ),
4077 startLength = queue.length,
4078 fn = queue.shift(),
4079 hooks = jQuery._queueHooks( elem, type ),
4080 next = function() {
4081 jQuery.dequeue( elem, type );
4082 };
4083
4084 // If the fx queue is dequeued, always remove the progress sentinel
4085 if ( fn === "inprogress" ) {
4086 fn = queue.shift();
4087 startLength--;
4088 }
4089
4090 if ( fn ) {
4091
4092 // Add a progress sentinel to prevent the fx queue from being
4093 // automatically dequeued
4094 if ( type === "fx" ) {
4095 queue.unshift( "inprogress" );
4096 }
4097
4098 // clear up the last queue stop function
4099 delete hooks.stop;
4100 fn.call( elem, next, hooks );
4101 }
4102
4103 if ( !startLength && hooks ) {
4104 hooks.empty.fire();
4105 }
4106 },
4107
4108 // not intended for public consumption - generates a queueHooks object, or returns the current one
4109 _queueHooks: function( elem, type ) {
4110 var key = type + "queueHooks";
4111 return jQuery._data( elem, key ) || jQuery._data( elem, key, {
4112 empty: jQuery.Callbacks("once memory").add(function() {
4113 jQuery._removeData( elem, type + "queue" );
4114 jQuery._removeData( elem, key );
4115 })
4116 });
4117 }
4118});
4119
4120jQuery.fn.extend({
4121 queue: function( type, data ) {
4122 var setter = 2;
4123
4124 if ( typeof type !== "string" ) {
4125 data = type;
4126 type = "fx";
4127 setter--;
4128 }
4129
4130 if ( arguments.length < setter ) {
4131 return jQuery.queue( this[0], type );
4132 }
4133
4134 return data === undefined ?
4135 this :
4136 this.each(function() {
4137 var queue = jQuery.queue( this, type, data );
4138
4139 // ensure a hooks for this queue
4140 jQuery._queueHooks( this, type );
4141
4142 if ( type === "fx" && queue[0] !== "inprogress" ) {
4143 jQuery.dequeue( this, type );
4144 }
4145 });
4146 },
4147 dequeue: function( type ) {
4148 return this.each(function() {
4149 jQuery.dequeue( this, type );
4150 });
4151 },
4152 clearQueue: function( type ) {
4153 return this.queue( type || "fx", [] );
4154 },
4155 // Get a promise resolved when queues of a certain type
4156 // are emptied (fx is the type by default)
4157 promise: function( type, obj ) {
4158 var tmp,
4159 count = 1,
4160 defer = jQuery.Deferred(),
4161 elements = this,
4162 i = this.length,
4163 resolve = function() {
4164 if ( !( --count ) ) {
4165 defer.resolveWith( elements, [ elements ] );
4166 }
4167 };
4168
4169 if ( typeof type !== "string" ) {
4170 obj = type;
4171 type = undefined;
4172 }
4173 type = type || "fx";
4174
4175 while ( i-- ) {
4176 tmp = jQuery._data( elements[ i ], type + "queueHooks" );
4177 if ( tmp && tmp.empty ) {
4178 count++;
4179 tmp.empty.add( resolve );
4180 }
4181 }
4182 resolve();
4183 return defer.promise( obj );
4184 }
4185});
4186var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
4187
4188var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
4189
4190var isHidden = function( elem, el ) {
4191 // isHidden might be called from jQuery#filter function;
4192 // in that case, element will be second argument
4193 elem = el || elem;
4194 return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
4195 };
4196
4197
4198
4199// Multifunctional method to get and set values of a collection
4200// The value/s can optionally be executed if it's a function
4201var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
4202 var i = 0,
4203 length = elems.length,
4204 bulk = key == null;
4205
4206 // Sets many values
4207 if ( jQuery.type( key ) === "object" ) {
4208 chainable = true;
4209 for ( i in key ) {
4210 jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
4211 }
4212
4213 // Sets one value
4214 } else if ( value !== undefined ) {
4215 chainable = true;
4216
4217 if ( !jQuery.isFunction( value ) ) {
4218 raw = true;
4219 }
4220
4221 if ( bulk ) {
4222 // Bulk operations run against the entire set
4223 if ( raw ) {
4224 fn.call( elems, value );
4225 fn = null;
4226
4227 // ...except when executing function values
4228 } else {
4229 bulk = fn;
4230 fn = function( elem, key, value ) {
4231 return bulk.call( jQuery( elem ), value );
4232 };
4233 }
4234 }
4235
4236 if ( fn ) {
4237 for ( ; i < length; i++ ) {
4238 fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
4239 }
4240 }
4241 }
4242
4243 return chainable ?
4244 elems :
4245
4246 // Gets
4247 bulk ?
4248 fn.call( elems ) :
4249 length ? fn( elems[0], key ) : emptyGet;
4250};
4251var rcheckableType = (/^(?:checkbox|radio)$/i);
4252
4253
4254
4255(function() {
4256 // Minified: var a,b,c
4257 var input = document.createElement( "input" ),
4258 div = document.createElement( "div" ),
4259 fragment = document.createDocumentFragment();
4260
4261 // Setup
4262 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
4263
4264 // IE strips leading whitespace when .innerHTML is used
4265 support.leadingWhitespace = div.firstChild.nodeType === 3;
4266
4267 // Make sure that tbody elements aren't automatically inserted
4268 // IE will insert them into empty tables
4269 support.tbody = !div.getElementsByTagName( "tbody" ).length;
4270
4271 // Make sure that link elements get serialized correctly by innerHTML
4272 // This requires a wrapper element in IE
4273 support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
4274
4275 // Makes sure cloning an html5 element does not cause problems
4276 // Where outerHTML is undefined, this still works
4277 support.html5Clone =
4278 document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
4279
4280 // Check if a disconnected checkbox will retain its checked
4281 // value of true after appended to the DOM (IE6/7)
4282 input.type = "checkbox";
4283 input.checked = true;
4284 fragment.appendChild( input );
4285 support.appendChecked = input.checked;
4286
4287 // Make sure textarea (and checkbox) defaultValue is properly cloned
4288 // Support: IE6-IE11+
4289 div.innerHTML = "<textarea>x</textarea>";
4290 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4291
4292 // #11217 - WebKit loses check when the name is after the checked attribute
4293 fragment.appendChild( div );
4294 div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
4295
4296 // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
4297 // old WebKit doesn't clone checked state correctly in fragments
4298 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4299
4300 // Support: IE<9
4301 // Opera does not clone events (and typeof div.attachEvent === undefined).
4302 // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
4303 support.noCloneEvent = true;
4304 if ( div.attachEvent ) {
4305 div.attachEvent( "onclick", function() {
4306 support.noCloneEvent = false;
4307 });
4308
4309 div.cloneNode( true ).click();
4310 }
4311
4312 // Execute the test only if not already executed in another module.
4313 if (support.deleteExpando == null) {
4314 // Support: IE<9
4315 support.deleteExpando = true;
4316 try {
4317 delete div.test;
4318 } catch( e ) {
4319 support.deleteExpando = false;
4320 }
4321 }
4322})();
4323
4324
4325(function() {
4326 var i, eventName,
4327 div = document.createElement( "div" );
4328
4329 // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
4330 for ( i in { submit: true, change: true, focusin: true }) {
4331 eventName = "on" + i;
4332
4333 if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
4334 // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
4335 div.setAttribute( eventName, "t" );
4336 support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
4337 }
4338 }
4339
4340 // Null elements to avoid leaks in IE.
4341 div = null;
4342})();
4343
4344
4345var rformElems = /^(?:input|select|textarea)$/i,
4346 rkeyEvent = /^key/,
4347 rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
4348 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
4349 rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
4350
4351function returnTrue() {
4352 return true;
4353}
4354
4355function returnFalse() {
4356 return false;
4357}
4358
4359function safeActiveElement() {
4360 try {
4361 return document.activeElement;
4362 } catch ( err ) { }
4363}
4364
4365/*
4366 * Helper functions for managing events -- not part of the public interface.
4367 * Props to Dean Edwards' addEvent library for many of the ideas.
4368 */
4369jQuery.event = {
4370
4371 global: {},
4372
4373 add: function( elem, types, handler, data, selector ) {
4374 var tmp, events, t, handleObjIn,
4375 special, eventHandle, handleObj,
4376 handlers, type, namespaces, origType,
4377 elemData = jQuery._data( elem );
4378
4379 // Don't attach events to noData or text/comment nodes (but allow plain objects)
4380 if ( !elemData ) {
4381 return;
4382 }
4383
4384 // Caller can pass in an object of custom data in lieu of the handler
4385 if ( handler.handler ) {
4386 handleObjIn = handler;
4387 handler = handleObjIn.handler;
4388 selector = handleObjIn.selector;
4389 }
4390
4391 // Make sure that the handler has a unique ID, used to find/remove it later
4392 if ( !handler.guid ) {
4393 handler.guid = jQuery.guid++;
4394 }
4395
4396 // Init the element's event structure and main handler, if this is the first
4397 if ( !(events = elemData.events) ) {
4398 events = elemData.events = {};
4399 }
4400 if ( !(eventHandle = elemData.handle) ) {
4401 eventHandle = elemData.handle = function( e ) {
4402 // Discard the second event of a jQuery.event.trigger() and
4403 // when an event is called after a page has unloaded
4404 return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
4405 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
4406 undefined;
4407 };
4408 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
4409 eventHandle.elem = elem;
4410 }
4411
4412 // Handle multiple events separated by a space
4413 types = ( types || "" ).match( rnotwhite ) || [ "" ];
4414 t = types.length;
4415 while ( t-- ) {
4416 tmp = rtypenamespace.exec( types[t] ) || [];
4417 type = origType = tmp[1];
4418 namespaces = ( tmp[2] || "" ).split( "." ).sort();
4419
4420 // There *must* be a type, no attaching namespace-only handlers
4421 if ( !type ) {
4422 continue;
4423 }
4424
4425 // If event changes its type, use the special event handlers for the changed type
4426 special = jQuery.event.special[ type ] || {};
4427
4428 // If selector defined, determine special event api type, otherwise given type
4429 type = ( selector ? special.delegateType : special.bindType ) || type;
4430
4431 // Update special based on newly reset type
4432 special = jQuery.event.special[ type ] || {};
4433
4434 // handleObj is passed to all event handlers
4435 handleObj = jQuery.extend({
4436 type: type,
4437 origType: origType,
4438 data: data,
4439 handler: handler,
4440 guid: handler.guid,
4441 selector: selector,
4442 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
4443 namespace: namespaces.join(".")
4444 }, handleObjIn );
4445
4446 // Init the event handler queue if we're the first
4447 if ( !(handlers = events[ type ]) ) {
4448 handlers = events[ type ] = [];
4449 handlers.delegateCount = 0;
4450
4451 // Only use addEventListener/attachEvent if the special events handler returns false
4452 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
4453 // Bind the global event handler to the element
4454 if ( elem.addEventListener ) {
4455 elem.addEventListener( type, eventHandle, false );
4456
4457 } else if ( elem.attachEvent ) {
4458 elem.attachEvent( "on" + type, eventHandle );
4459 }
4460 }
4461 }
4462
4463 if ( special.add ) {
4464 special.add.call( elem, handleObj );
4465
4466 if ( !handleObj.handler.guid ) {
4467 handleObj.handler.guid = handler.guid;
4468 }
4469 }
4470
4471 // Add to the element's handler list, delegates in front
4472 if ( selector ) {
4473 handlers.splice( handlers.delegateCount++, 0, handleObj );
4474 } else {
4475 handlers.push( handleObj );
4476 }
4477
4478 // Keep track of which events have ever been used, for event optimization
4479 jQuery.event.global[ type ] = true;
4480 }
4481
4482 // Nullify elem to prevent memory leaks in IE
4483 elem = null;
4484 },
4485
4486 // Detach an event or set of events from an element
4487 remove: function( elem, types, handler, selector, mappedTypes ) {
4488 var j, handleObj, tmp,
4489 origCount, t, events,
4490 special, handlers, type,
4491 namespaces, origType,
4492 elemData = jQuery.hasData( elem ) && jQuery._data( elem );
4493
4494 if ( !elemData || !(events = elemData.events) ) {
4495 return;
4496 }
4497
4498 // Once for each type.namespace in types; type may be omitted
4499 types = ( types || "" ).match( rnotwhite ) || [ "" ];
4500 t = types.length;
4501 while ( t-- ) {
4502 tmp = rtypenamespace.exec( types[t] ) || [];
4503 type = origType = tmp[1];
4504 namespaces = ( tmp[2] || "" ).split( "." ).sort();
4505
4506 // Unbind all events (on this namespace, if provided) for the element
4507 if ( !type ) {
4508 for ( type in events ) {
4509 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
4510 }
4511 continue;
4512 }
4513
4514 special = jQuery.event.special[ type ] || {};
4515 type = ( selector ? special.delegateType : special.bindType ) || type;
4516 handlers = events[ type ] || [];
4517 tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
4518
4519 // Remove matching events
4520 origCount = j = handlers.length;
4521 while ( j-- ) {
4522 handleObj = handlers[ j ];
4523
4524 if ( ( mappedTypes || origType === handleObj.origType ) &&
4525 ( !handler || handler.guid === handleObj.guid ) &&
4526 ( !tmp || tmp.test( handleObj.namespace ) ) &&
4527 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
4528 handlers.splice( j, 1 );
4529
4530 if ( handleObj.selector ) {
4531 handlers.delegateCount--;
4532 }
4533 if ( special.remove ) {
4534 special.remove.call( elem, handleObj );
4535 }
4536 }
4537 }
4538
4539 // Remove generic event handler if we removed something and no more handlers exist
4540 // (avoids potential for endless recursion during removal of special event handlers)
4541 if ( origCount && !handlers.length ) {
4542 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
4543 jQuery.removeEvent( elem, type, elemData.handle );
4544 }
4545
4546 delete events[ type ];
4547 }
4548 }
4549
4550 // Remove the expando if it's no longer used
4551 if ( jQuery.isEmptyObject( events ) ) {
4552 delete elemData.handle;
4553
4554 // removeData also checks for emptiness and clears the expando if empty
4555 // so use it instead of delete
4556 jQuery._removeData( elem, "events" );
4557 }
4558 },
4559
4560 trigger: function( event, data, elem, onlyHandlers ) {
4561 var handle, ontype, cur,
4562 bubbleType, special, tmp, i,
4563 eventPath = [ elem || document ],
4564 type = hasOwn.call( event, "type" ) ? event.type : event,
4565 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
4566
4567 cur = tmp = elem = elem || document;
4568
4569 // Don't do events on text and comment nodes
4570 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
4571 return;
4572 }
4573
4574 // focus/blur morphs to focusin/out; ensure we're not firing them right now
4575 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
4576 return;
4577 }
4578
4579 if ( type.indexOf(".") >= 0 ) {
4580 // Namespaced trigger; create a regexp to match event type in handle()
4581 namespaces = type.split(".");
4582 type = namespaces.shift();
4583 namespaces.sort();
4584 }
4585 ontype = type.indexOf(":") < 0 && "on" + type;
4586
4587 // Caller can pass in a jQuery.Event object, Object, or just an event type string
4588 event = event[ jQuery.expando ] ?
4589 event :
4590 new jQuery.Event( type, typeof event === "object" && event );
4591
4592 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
4593 event.isTrigger = onlyHandlers ? 2 : 3;
4594 event.namespace = namespaces.join(".");
4595 event.namespace_re = event.namespace ?
4596 new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
4597 null;
4598
4599 // Clean up the event in case it is being reused
4600 event.result = undefined;
4601 if ( !event.target ) {
4602 event.target = elem;
4603 }
4604
4605 // Clone any incoming data and prepend the event, creating the handler arg list
4606 data = data == null ?
4607 [ event ] :
4608 jQuery.makeArray( data, [ event ] );
4609
4610 // Allow special events to draw outside the lines
4611 special = jQuery.event.special[ type ] || {};
4612 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
4613 return;
4614 }
4615
4616 // Determine event propagation path in advance, per W3C events spec (#9951)
4617 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
4618 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
4619
4620 bubbleType = special.delegateType || type;
4621 if ( !rfocusMorph.test( bubbleType + type ) ) {
4622 cur = cur.parentNode;
4623 }
4624 for ( ; cur; cur = cur.parentNode ) {
4625 eventPath.push( cur );
4626 tmp = cur;
4627 }
4628
4629 // Only add window if we got to document (e.g., not plain obj or detached DOM)
4630 if ( tmp === (elem.ownerDocument || document) ) {
4631 eventPath.push( tmp.defaultView || tmp.parentWindow || window );
4632 }
4633 }
4634
4635 // Fire handlers on the event path
4636 i = 0;
4637 while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
4638
4639 event.type = i > 1 ?
4640 bubbleType :
4641 special.bindType || type;
4642
4643 // jQuery handler
4644 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
4645 if ( handle ) {
4646 handle.apply( cur, data );
4647 }
4648
4649 // Native handler
4650 handle = ontype && cur[ ontype ];
4651 if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
4652 event.result = handle.apply( cur, data );
4653 if ( event.result === false ) {
4654 event.preventDefault();
4655 }
4656 }
4657 }
4658 event.type = type;
4659
4660 // If nobody prevented the default action, do it now
4661 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
4662
4663 if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
4664 jQuery.acceptData( elem ) ) {
4665
4666 // Call a native DOM method on the target with the same name name as the event.
4667 // Can't use an .isFunction() check here because IE6/7 fails that test.
4668 // Don't do default actions on window, that's where global variables be (#6170)
4669 if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
4670
4671 // Don't re-trigger an onFOO event when we call its FOO() method
4672 tmp = elem[ ontype ];
4673
4674 if ( tmp ) {
4675 elem[ ontype ] = null;
4676 }
4677
4678 // Prevent re-triggering of the same event, since we already bubbled it above
4679 jQuery.event.triggered = type;
4680 try {
4681 elem[ type ]();
4682 } catch ( e ) {
4683 // IE<9 dies on focus/blur to hidden element (#1486,#12518)
4684 // only reproducible on winXP IE8 native, not IE9 in IE8 mode
4685 }
4686 jQuery.event.triggered = undefined;
4687
4688 if ( tmp ) {
4689 elem[ ontype ] = tmp;
4690 }
4691 }
4692 }
4693 }
4694
4695 return event.result;
4696 },
4697
4698 dispatch: function( event ) {
4699
4700 // Make a writable jQuery.Event from the native event object
4701 event = jQuery.event.fix( event );
4702
4703 var i, ret, handleObj, matched, j,
4704 handlerQueue = [],
4705 args = slice.call( arguments ),
4706 handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
4707 special = jQuery.event.special[ event.type ] || {};
4708
4709 // Use the fix-ed jQuery.Event rather than the (read-only) native event
4710 args[0] = event;
4711 event.delegateTarget = this;
4712
4713 // Call the preDispatch hook for the mapped type, and let it bail if desired
4714 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
4715 return;
4716 }
4717
4718 // Determine handlers
4719 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
4720
4721 // Run delegates first; they may want to stop propagation beneath us
4722 i = 0;
4723 while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
4724 event.currentTarget = matched.elem;
4725
4726 j = 0;
4727 while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
4728
4729 // Triggered event must either 1) have no namespace, or
4730 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
4731 if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
4732
4733 event.handleObj = handleObj;
4734 event.data = handleObj.data;
4735
4736 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
4737 .apply( matched.elem, args );
4738
4739 if ( ret !== undefined ) {
4740 if ( (event.result = ret) === false ) {
4741 event.preventDefault();
4742 event.stopPropagation();
4743 }
4744 }
4745 }
4746 }
4747 }
4748
4749 // Call the postDispatch hook for the mapped type
4750 if ( special.postDispatch ) {
4751 special.postDispatch.call( this, event );
4752 }
4753
4754 return event.result;
4755 },
4756
4757 handlers: function( event, handlers ) {
4758 var sel, handleObj, matches, i,
4759 handlerQueue = [],
4760 delegateCount = handlers.delegateCount,
4761 cur = event.target;
4762
4763 // Find delegate handlers
4764 // Black-hole SVG <use> instance trees (#13180)
4765 // Avoid non-left-click bubbling in Firefox (#3861)
4766 if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
4767
4768 /* jshint eqeqeq: false */
4769 for ( ; cur != this; cur = cur.parentNode || this ) {
4770 /* jshint eqeqeq: true */
4771
4772 // Don't check non-elements (#13208)
4773 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
4774 if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
4775 matches = [];
4776 for ( i = 0; i < delegateCount; i++ ) {
4777 handleObj = handlers[ i ];
4778
4779 // Don't conflict with Object.prototype properties (#13203)
4780 sel = handleObj.selector + " ";
4781
4782 if ( matches[ sel ] === undefined ) {
4783 matches[ sel ] = handleObj.needsContext ?
4784 jQuery( sel, this ).index( cur ) >= 0 :
4785 jQuery.find( sel, this, null, [ cur ] ).length;
4786 }
4787 if ( matches[ sel ] ) {
4788 matches.push( handleObj );
4789 }
4790 }
4791 if ( matches.length ) {
4792 handlerQueue.push({ elem: cur, handlers: matches });
4793 }
4794 }
4795 }
4796 }
4797
4798 // Add the remaining (directly-bound) handlers
4799 if ( delegateCount < handlers.length ) {
4800 handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
4801 }
4802
4803 return handlerQueue;
4804 },
4805
4806 fix: function( event ) {
4807 if ( event[ jQuery.expando ] ) {
4808 return event;
4809 }
4810
4811 // Create a writable copy of the event object and normalize some properties
4812 var i, prop, copy,
4813 type = event.type,
4814 originalEvent = event,
4815 fixHook = this.fixHooks[ type ];
4816
4817 if ( !fixHook ) {
4818 this.fixHooks[ type ] = fixHook =
4819 rmouseEvent.test( type ) ? this.mouseHooks :
4820 rkeyEvent.test( type ) ? this.keyHooks :
4821 {};
4822 }
4823 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
4824
4825 event = new jQuery.Event( originalEvent );
4826
4827 i = copy.length;
4828 while ( i-- ) {
4829 prop = copy[ i ];
4830 event[ prop ] = originalEvent[ prop ];
4831 }
4832
4833 // Support: IE<9
4834 // Fix target property (#1925)
4835 if ( !event.target ) {
4836 event.target = originalEvent.srcElement || document;
4837 }
4838
4839 // Support: Chrome 23+, Safari?
4840 // Target should not be a text node (#504, #13143)
4841 if ( event.target.nodeType === 3 ) {
4842 event.target = event.target.parentNode;
4843 }
4844
4845 // Support: IE<9
4846 // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
4847 event.metaKey = !!event.metaKey;
4848
4849 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
4850 },
4851
4852 // Includes some event props shared by KeyEvent and MouseEvent
4853 props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
4854
4855 fixHooks: {},
4856
4857 keyHooks: {
4858 props: "char charCode key keyCode".split(" "),
4859 filter: function( event, original ) {
4860
4861 // Add which for key events
4862 if ( event.which == null ) {
4863 event.which = original.charCode != null ? original.charCode : original.keyCode;
4864 }
4865
4866 return event;
4867 }
4868 },
4869
4870 mouseHooks: {
4871 props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
4872 filter: function( event, original ) {
4873 var body, eventDoc, doc,
4874 button = original.button,
4875 fromElement = original.fromElement;
4876
4877 // Calculate pageX/Y if missing and clientX/Y available
4878 if ( event.pageX == null && original.clientX != null ) {
4879 eventDoc = event.target.ownerDocument || document;
4880 doc = eventDoc.documentElement;
4881 body = eventDoc.body;
4882
4883 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
4884 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
4885 }
4886
4887 // Add relatedTarget, if necessary
4888 if ( !event.relatedTarget && fromElement ) {
4889 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
4890 }
4891
4892 // Add which for click: 1 === left; 2 === middle; 3 === right
4893 // Note: button is not normalized, so don't use it
4894 if ( !event.which && button !== undefined ) {
4895 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
4896 }
4897
4898 return event;
4899 }
4900 },
4901
4902 special: {
4903 load: {
4904 // Prevent triggered image.load events from bubbling to window.load
4905 noBubble: true
4906 },
4907 focus: {
4908 // Fire native event if possible so blur/focus sequence is correct
4909 trigger: function() {
4910 if ( this !== safeActiveElement() && this.focus ) {
4911 try {
4912 this.focus();
4913 return false;
4914 } catch ( e ) {
4915 // Support: IE<9
4916 // If we error on focus to hidden element (#1486, #12518),
4917 // let .trigger() run the handlers
4918 }
4919 }
4920 },
4921 delegateType: "focusin"
4922 },
4923 blur: {
4924 trigger: function() {
4925 if ( this === safeActiveElement() && this.blur ) {
4926 this.blur();
4927 return false;
4928 }
4929 },
4930 delegateType: "focusout"
4931 },
4932 click: {
4933 // For checkbox, fire native event so checked state will be right
4934 trigger: function() {
4935 if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
4936 this.click();
4937 return false;
4938 }
4939 },
4940
4941 // For cross-browser consistency, don't fire native .click() on links
4942 _default: function( event ) {
4943 return jQuery.nodeName( event.target, "a" );
4944 }
4945 },
4946
4947 beforeunload: {
4948 postDispatch: function( event ) {
4949
4950 // Support: Firefox 20+
4951 // Firefox doesn't alert if the returnValue field is not set.
4952 if ( event.result !== undefined && event.originalEvent ) {
4953 event.originalEvent.returnValue = event.result;
4954 }
4955 }
4956 }
4957 },
4958
4959 simulate: function( type, elem, event, bubble ) {
4960 // Piggyback on a donor event to simulate a different one.
4961 // Fake originalEvent to avoid donor's stopPropagation, but if the
4962 // simulated event prevents default then we do the same on the donor.
4963 var e = jQuery.extend(
4964 new jQuery.Event(),
4965 event,
4966 {
4967 type: type,
4968 isSimulated: true,
4969 originalEvent: {}
4970 }
4971 );
4972 if ( bubble ) {
4973 jQuery.event.trigger( e, null, elem );
4974 } else {
4975 jQuery.event.dispatch.call( elem, e );
4976 }
4977 if ( e.isDefaultPrevented() ) {
4978 event.preventDefault();
4979 }
4980 }
4981};
4982
4983jQuery.removeEvent = document.removeEventListener ?
4984 function( elem, type, handle ) {
4985 if ( elem.removeEventListener ) {
4986 elem.removeEventListener( type, handle, false );
4987 }
4988 } :
4989 function( elem, type, handle ) {
4990 var name = "on" + type;
4991
4992 if ( elem.detachEvent ) {
4993
4994 // #8545, #7054, preventing memory leaks for custom events in IE6-8
4995 // detachEvent needed property on element, by name of that event, to properly expose it to GC
4996 if ( typeof elem[ name ] === strundefined ) {
4997 elem[ name ] = null;
4998 }
4999
5000 elem.detachEvent( name, handle );
5001 }
5002 };
5003
5004jQuery.Event = function( src, props ) {
5005 // Allow instantiation without the 'new' keyword
5006 if ( !(this instanceof jQuery.Event) ) {
5007 return new jQuery.Event( src, props );
5008 }
5009
5010 // Event object
5011 if ( src && src.type ) {
5012 this.originalEvent = src;
5013 this.type = src.type;
5014
5015 // Events bubbling up the document may have been marked as prevented
5016 // by a handler lower down the tree; reflect the correct value.
5017 this.isDefaultPrevented = src.defaultPrevented ||
5018 src.defaultPrevented === undefined &&
5019 // Support: IE < 9, Android < 4.0
5020 src.returnValue === false ?
5021 returnTrue :
5022 returnFalse;
5023
5024 // Event type
5025 } else {
5026 this.type = src;
5027 }
5028
5029 // Put explicitly provided properties onto the event object
5030 if ( props ) {
5031 jQuery.extend( this, props );
5032 }
5033
5034 // Create a timestamp if incoming event doesn't have one
5035 this.timeStamp = src && src.timeStamp || jQuery.now();
5036
5037 // Mark it as fixed
5038 this[ jQuery.expando ] = true;
5039};
5040
5041// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
5042// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
5043jQuery.Event.prototype = {
5044 isDefaultPrevented: returnFalse,
5045 isPropagationStopped: returnFalse,
5046 isImmediatePropagationStopped: returnFalse,
5047
5048 preventDefault: function() {
5049 var e = this.originalEvent;
5050
5051 this.isDefaultPrevented = returnTrue;
5052 if ( !e ) {
5053 return;
5054 }
5055
5056 // If preventDefault exists, run it on the original event
5057 if ( e.preventDefault ) {
5058 e.preventDefault();
5059
5060 // Support: IE
5061 // Otherwise set the returnValue property of the original event to false
5062 } else {
5063 e.returnValue = false;
5064 }
5065 },
5066 stopPropagation: function() {
5067 var e = this.originalEvent;
5068
5069 this.isPropagationStopped = returnTrue;
5070 if ( !e ) {
5071 return;
5072 }
5073 // If stopPropagation exists, run it on the original event
5074 if ( e.stopPropagation ) {
5075 e.stopPropagation();
5076 }
5077
5078 // Support: IE
5079 // Set the cancelBubble property of the original event to true
5080 e.cancelBubble = true;
5081 },
5082 stopImmediatePropagation: function() {
5083 var e = this.originalEvent;
5084
5085 this.isImmediatePropagationStopped = returnTrue;
5086
5087 if ( e && e.stopImmediatePropagation ) {
5088 e.stopImmediatePropagation();
5089 }
5090
5091 this.stopPropagation();
5092 }
5093};
5094
5095// Create mouseenter/leave events using mouseover/out and event-time checks
5096jQuery.each({
5097 mouseenter: "mouseover",
5098 mouseleave: "mouseout",
5099 pointerenter: "pointerover",
5100 pointerleave: "pointerout"
5101}, function( orig, fix ) {
5102 jQuery.event.special[ orig ] = {
5103 delegateType: fix,
5104 bindType: fix,
5105
5106 handle: function( event ) {
5107 var ret,
5108 target = this,
5109 related = event.relatedTarget,
5110 handleObj = event.handleObj;
5111
5112 // For mousenter/leave call the handler if related is outside the target.
5113 // NB: No relatedTarget if the mouse left/entered the browser window
5114 if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
5115 event.type = handleObj.origType;
5116 ret = handleObj.handler.apply( this, arguments );
5117 event.type = fix;
5118 }
5119 return ret;
5120 }
5121 };
5122});
5123
5124// IE submit delegation
5125if ( !support.submitBubbles ) {
5126
5127 jQuery.event.special.submit = {
5128 setup: function() {
5129 // Only need this for delegated form submit events
5130 if ( jQuery.nodeName( this, "form" ) ) {
5131 return false;
5132 }
5133
5134 // Lazy-add a submit handler when a descendant form may potentially be submitted
5135 jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
5136 // Node name check avoids a VML-related crash in IE (#9807)
5137 var elem = e.target,
5138 form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
5139 if ( form && !jQuery._data( form, "submitBubbles" ) ) {
5140 jQuery.event.add( form, "submit._submit", function( event ) {
5141 event._submit_bubble = true;
5142 });
5143 jQuery._data( form, "submitBubbles", true );
5144 }
5145 });
5146 // return undefined since we don't need an event listener
5147 },
5148
5149 postDispatch: function( event ) {
5150 // If form was submitted by the user, bubble the event up the tree
5151 if ( event._submit_bubble ) {
5152 delete event._submit_bubble;
5153 if ( this.parentNode && !event.isTrigger ) {
5154 jQuery.event.simulate( "submit", this.parentNode, event, true );
5155 }
5156 }
5157 },
5158
5159 teardown: function() {
5160 // Only need this for delegated form submit events
5161 if ( jQuery.nodeName( this, "form" ) ) {
5162 return false;
5163 }
5164
5165 // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
5166 jQuery.event.remove( this, "._submit" );
5167 }
5168 };
5169}
5170
5171// IE change delegation and checkbox/radio fix
5172if ( !support.changeBubbles ) {
5173
5174 jQuery.event.special.change = {
5175
5176 setup: function() {
5177
5178 if ( rformElems.test( this.nodeName ) ) {
5179 // IE doesn't fire change on a check/radio until blur; trigger it on click
5180 // after a propertychange. Eat the blur-change in special.change.handle.
5181 // This still fires onchange a second time for check/radio after blur.
5182 if ( this.type === "checkbox" || this.type === "radio" ) {
5183 jQuery.event.add( this, "propertychange._change", function( event ) {
5184 if ( event.originalEvent.propertyName === "checked" ) {
5185 this._just_changed = true;
5186 }
5187 });
5188 jQuery.event.add( this, "click._change", function( event ) {
5189 if ( this._just_changed && !event.isTrigger ) {
5190 this._just_changed = false;
5191 }
5192 // Allow triggered, simulated change events (#11500)
5193 jQuery.event.simulate( "change", this, event, true );
5194 });
5195 }
5196 return false;
5197 }
5198 // Delegated event; lazy-add a change handler on descendant inputs
5199 jQuery.event.add( this, "beforeactivate._change", function( e ) {
5200 var elem = e.target;
5201
5202 if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
5203 jQuery.event.add( elem, "change._change", function( event ) {
5204 if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
5205 jQuery.event.simulate( "change", this.parentNode, event, true );
5206 }
5207 });
5208 jQuery._data( elem, "changeBubbles", true );
5209 }
5210 });
5211 },
5212
5213 handle: function( event ) {
5214 var elem = event.target;
5215
5216 // Swallow native change events from checkbox/radio, we already triggered them above
5217 if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
5218 return event.handleObj.handler.apply( this, arguments );
5219 }
5220 },
5221
5222 teardown: function() {
5223 jQuery.event.remove( this, "._change" );
5224
5225 return !rformElems.test( this.nodeName );
5226 }
5227 };
5228}
5229
5230// Create "bubbling" focus and blur events
5231if ( !support.focusinBubbles ) {
5232 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
5233
5234 // Attach a single capturing handler on the document while someone wants focusin/focusout
5235 var handler = function( event ) {
5236 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
5237 };
5238
5239 jQuery.event.special[ fix ] = {
5240 setup: function() {
5241 var doc = this.ownerDocument || this,
5242 attaches = jQuery._data( doc, fix );
5243
5244 if ( !attaches ) {
5245 doc.addEventListener( orig, handler, true );
5246 }
5247 jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
5248 },
5249 teardown: function() {
5250 var doc = this.ownerDocument || this,
5251 attaches = jQuery._data( doc, fix ) - 1;
5252
5253 if ( !attaches ) {
5254 doc.removeEventListener( orig, handler, true );
5255 jQuery._removeData( doc, fix );
5256 } else {
5257 jQuery._data( doc, fix, attaches );
5258 }
5259 }
5260 };
5261 });
5262}
5263
5264jQuery.fn.extend({
5265
5266 on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
5267 var type, origFn;
5268
5269 // Types can be a map of types/handlers
5270 if ( typeof types === "object" ) {
5271 // ( types-Object, selector, data )
5272 if ( typeof selector !== "string" ) {
5273 // ( types-Object, data )
5274 data = data || selector;
5275 selector = undefined;
5276 }
5277 for ( type in types ) {
5278 this.on( type, selector, data, types[ type ], one );
5279 }
5280 return this;
5281 }
5282
5283 if ( data == null && fn == null ) {
5284 // ( types, fn )
5285 fn = selector;
5286 data = selector = undefined;
5287 } else if ( fn == null ) {
5288 if ( typeof selector === "string" ) {
5289 // ( types, selector, fn )
5290 fn = data;
5291 data = undefined;
5292 } else {
5293 // ( types, data, fn )
5294 fn = data;
5295 data = selector;
5296 selector = undefined;
5297 }
5298 }
5299 if ( fn === false ) {
5300 fn = returnFalse;
5301 } else if ( !fn ) {
5302 return this;
5303 }
5304
5305 if ( one === 1 ) {
5306 origFn = fn;
5307 fn = function( event ) {
5308 // Can use an empty set, since event contains the info
5309 jQuery().off( event );
5310 return origFn.apply( this, arguments );
5311 };
5312 // Use same guid so caller can remove using origFn
5313 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
5314 }
5315 return this.each( function() {
5316 jQuery.event.add( this, types, fn, data, selector );
5317 });
5318 },
5319 one: function( types, selector, data, fn ) {
5320 return this.on( types, selector, data, fn, 1 );
5321 },
5322 off: function( types, selector, fn ) {
5323 var handleObj, type;
5324 if ( types && types.preventDefault && types.handleObj ) {
5325 // ( event ) dispatched jQuery.Event
5326 handleObj = types.handleObj;
5327 jQuery( types.delegateTarget ).off(
5328 handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
5329 handleObj.selector,
5330 handleObj.handler
5331 );
5332 return this;
5333 }
5334 if ( typeof types === "object" ) {
5335 // ( types-object [, selector] )
5336 for ( type in types ) {
5337 this.off( type, selector, types[ type ] );
5338 }
5339 return this;
5340 }
5341 if ( selector === false || typeof selector === "function" ) {
5342 // ( types [, fn] )
5343 fn = selector;
5344 selector = undefined;
5345 }
5346 if ( fn === false ) {
5347 fn = returnFalse;
5348 }
5349 return this.each(function() {
5350 jQuery.event.remove( this, types, fn, selector );
5351 });
5352 },
5353
5354 trigger: function( type, data ) {
5355 return this.each(function() {
5356 jQuery.event.trigger( type, data, this );
5357 });
5358 },
5359 triggerHandler: function( type, data ) {
5360 var elem = this[0];
5361 if ( elem ) {
5362 return jQuery.event.trigger( type, data, elem, true );
5363 }
5364 }
5365});
5366
5367
5368function createSafeFragment( document ) {
5369 var list = nodeNames.split( "|" ),
5370 safeFrag = document.createDocumentFragment();
5371
5372 if ( safeFrag.createElement ) {
5373 while ( list.length ) {
5374 safeFrag.createElement(
5375 list.pop()
5376 );
5377 }
5378 }
5379 return safeFrag;
5380}
5381
5382var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
5383 "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
5384 rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
5385 rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
5386 rleadingWhitespace = /^\s+/,
5387 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
5388 rtagName = /<([\w:]+)/,
5389 rtbody = /<tbody/i,
5390 rhtml = /<|&#?\w+;/,
5391 rnoInnerhtml = /<(?:script|style|link)/i,
5392 // checked="checked" or checked
5393 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5394 rscriptType = /^$|\/(?:java|ecma)script/i,
5395 rscriptTypeMasked = /^true\/(.*)/,
5396 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
5397
5398 // We have to close these tags to support XHTML (#13200)
5399 wrapMap = {
5400 option: [ 1, "<select multiple='multiple'>", "</select>" ],
5401 legend: [ 1, "<fieldset>", "</fieldset>" ],
5402 area: [ 1, "<map>", "</map>" ],
5403 param: [ 1, "<object>", "</object>" ],
5404 thead: [ 1, "<table>", "</table>" ],
5405 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
5406 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
5407 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
5408
5409 // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
5410 // unless wrapped in a div with non-breaking characters in front of it.
5411 _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
5412 },
5413 safeFragment = createSafeFragment( document ),
5414 fragmentDiv = safeFragment.appendChild( document.createElement("div") );
5415
5416wrapMap.optgroup = wrapMap.option;
5417wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
5418wrapMap.th = wrapMap.td;
5419
5420function getAll( context, tag ) {
5421 var elems, elem,
5422 i = 0,
5423 found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
5424 typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
5425 undefined;
5426
5427 if ( !found ) {
5428 for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
5429 if ( !tag || jQuery.nodeName( elem, tag ) ) {
5430 found.push( elem );
5431 } else {
5432 jQuery.merge( found, getAll( elem, tag ) );
5433 }
5434 }
5435 }
5436
5437 return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
5438 jQuery.merge( [ context ], found ) :
5439 found;
5440}
5441
5442// Used in buildFragment, fixes the defaultChecked property
5443function fixDefaultChecked( elem ) {
5444 if ( rcheckableType.test( elem.type ) ) {
5445 elem.defaultChecked = elem.checked;
5446 }
5447}
5448
5449// Support: IE<8
5450// Manipulating tables requires a tbody
5451function manipulationTarget( elem, content ) {
5452 return jQuery.nodeName( elem, "table" ) &&
5453 jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
5454
5455 elem.getElementsByTagName("tbody")[0] ||
5456 elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
5457 elem;
5458}
5459
5460// Replace/restore the type attribute of script elements for safe DOM manipulation
5461function disableScript( elem ) {
5462 elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
5463 return elem;
5464}
5465function restoreScript( elem ) {
5466 var match = rscriptTypeMasked.exec( elem.type );
5467 if ( match ) {
5468 elem.type = match[1];
5469 } else {
5470 elem.removeAttribute("type");
5471 }
5472 return elem;
5473}
5474
5475// Mark scripts as having already been evaluated
5476function setGlobalEval( elems, refElements ) {
5477 var elem,
5478 i = 0;
5479 for ( ; (elem = elems[i]) != null; i++ ) {
5480 jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
5481 }
5482}
5483
5484function cloneCopyEvent( src, dest ) {
5485
5486 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
5487 return;
5488 }
5489
5490 var type, i, l,
5491 oldData = jQuery._data( src ),
5492 curData = jQuery._data( dest, oldData ),
5493 events = oldData.events;
5494
5495 if ( events ) {
5496 delete curData.handle;
5497 curData.events = {};
5498
5499 for ( type in events ) {
5500 for ( i = 0, l = events[ type ].length; i < l; i++ ) {
5501 jQuery.event.add( dest, type, events[ type ][ i ] );
5502 }
5503 }
5504 }
5505
5506 // make the cloned public data object a copy from the original
5507 if ( curData.data ) {
5508 curData.data = jQuery.extend( {}, curData.data );
5509 }
5510}
5511
5512function fixCloneNodeIssues( src, dest ) {
5513 var nodeName, e, data;
5514
5515 // We do not need to do anything for non-Elements
5516 if ( dest.nodeType !== 1 ) {
5517 return;
5518 }
5519
5520 nodeName = dest.nodeName.toLowerCase();
5521
5522 // IE6-8 copies events bound via attachEvent when using cloneNode.
5523 if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
5524 data = jQuery._data( dest );
5525
5526 for ( e in data.events ) {
5527 jQuery.removeEvent( dest, e, data.handle );
5528 }
5529
5530 // Event data gets referenced instead of copied if the expando gets copied too
5531 dest.removeAttribute( jQuery.expando );
5532 }
5533
5534 // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
5535 if ( nodeName === "script" && dest.text !== src.text ) {
5536 disableScript( dest ).text = src.text;
5537 restoreScript( dest );
5538
5539 // IE6-10 improperly clones children of object elements using classid.
5540 // IE10 throws NoModificationAllowedError if parent is null, #12132.
5541 } else if ( nodeName === "object" ) {
5542 if ( dest.parentNode ) {
5543 dest.outerHTML = src.outerHTML;
5544 }
5545
5546 // This path appears unavoidable for IE9. When cloning an object
5547 // element in IE9, the outerHTML strategy above is not sufficient.
5548 // If the src has innerHTML and the destination does not,
5549 // copy the src.innerHTML into the dest.innerHTML. #10324
5550 if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
5551 dest.innerHTML = src.innerHTML;
5552 }
5553
5554 } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
5555 // IE6-8 fails to persist the checked state of a cloned checkbox
5556 // or radio button. Worse, IE6-7 fail to give the cloned element
5557 // a checked appearance if the defaultChecked value isn't also set
5558
5559 dest.defaultChecked = dest.checked = src.checked;
5560
5561 // IE6-7 get confused and end up setting the value of a cloned
5562 // checkbox/radio button to an empty string instead of "on"
5563 if ( dest.value !== src.value ) {
5564 dest.value = src.value;
5565 }
5566
5567 // IE6-8 fails to return the selected option to the default selected
5568 // state when cloning options
5569 } else if ( nodeName === "option" ) {
5570 dest.defaultSelected = dest.selected = src.defaultSelected;
5571
5572 // IE6-8 fails to set the defaultValue to the correct value when
5573 // cloning other types of input fields
5574 } else if ( nodeName === "input" || nodeName === "textarea" ) {
5575 dest.defaultValue = src.defaultValue;
5576 }
5577}
5578
5579jQuery.extend({
5580 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
5581 var destElements, node, clone, i, srcElements,
5582 inPage = jQuery.contains( elem.ownerDocument, elem );
5583
5584 if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
5585 clone = elem.cloneNode( true );
5586
5587 // IE<=8 does not properly clone detached, unknown element nodes
5588 } else {
5589 fragmentDiv.innerHTML = elem.outerHTML;
5590 fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
5591 }
5592
5593 if ( (!support.noCloneEvent || !support.noCloneChecked) &&
5594 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
5595
5596 // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
5597 destElements = getAll( clone );
5598 srcElements = getAll( elem );
5599
5600 // Fix all IE cloning issues
5601 for ( i = 0; (node = srcElements[i]) != null; ++i ) {
5602 // Ensure that the destination node is not null; Fixes #9587
5603 if ( destElements[i] ) {
5604 fixCloneNodeIssues( node, destElements[i] );
5605 }
5606 }
5607 }
5608
5609 // Copy the events from the original to the clone
5610 if ( dataAndEvents ) {
5611 if ( deepDataAndEvents ) {
5612 srcElements = srcElements || getAll( elem );
5613 destElements = destElements || getAll( clone );
5614
5615 for ( i = 0; (node = srcElements[i]) != null; i++ ) {
5616 cloneCopyEvent( node, destElements[i] );
5617 }
5618 } else {
5619 cloneCopyEvent( elem, clone );
5620 }
5621 }
5622
5623 // Preserve script evaluation history
5624 destElements = getAll( clone, "script" );
5625 if ( destElements.length > 0 ) {
5626 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
5627 }
5628
5629 destElements = srcElements = node = null;
5630
5631 // Return the cloned set
5632 return clone;
5633 },
5634
5635 buildFragment: function( elems, context, scripts, selection ) {
5636 var j, elem, contains,
5637 tmp, tag, tbody, wrap,
5638 l = elems.length,
5639
5640 // Ensure a safe fragment
5641 safe = createSafeFragment( context ),
5642
5643 nodes = [],
5644 i = 0;
5645
5646 for ( ; i < l; i++ ) {
5647 elem = elems[ i ];
5648
5649 if ( elem || elem === 0 ) {
5650
5651 // Add nodes directly
5652 if ( jQuery.type( elem ) === "object" ) {
5653 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
5654
5655 // Convert non-html into a text node
5656 } else if ( !rhtml.test( elem ) ) {
5657 nodes.push( context.createTextNode( elem ) );
5658
5659 // Convert html into DOM nodes
5660 } else {
5661 tmp = tmp || safe.appendChild( context.createElement("div") );
5662
5663 // Deserialize a standard representation
5664 tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
5665 wrap = wrapMap[ tag ] || wrapMap._default;
5666
5667 tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
5668
5669 // Descend through wrappers to the right content
5670 j = wrap[0];
5671 while ( j-- ) {
5672 tmp = tmp.lastChild;
5673 }
5674
5675 // Manually add leading whitespace removed by IE
5676 if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
5677 nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
5678 }
5679
5680 // Remove IE's autoinserted <tbody> from table fragments
5681 if ( !support.tbody ) {
5682
5683 // String was a <table>, *may* have spurious <tbody>
5684 elem = tag === "table" && !rtbody.test( elem ) ?
5685 tmp.firstChild :
5686
5687 // String was a bare <thead> or <tfoot>
5688 wrap[1] === "<table>" && !rtbody.test( elem ) ?
5689 tmp :
5690 0;
5691
5692 j = elem && elem.childNodes.length;
5693 while ( j-- ) {
5694 if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
5695 elem.removeChild( tbody );
5696 }
5697 }
5698 }
5699
5700 jQuery.merge( nodes, tmp.childNodes );
5701
5702 // Fix #12392 for WebKit and IE > 9
5703 tmp.textContent = "";
5704
5705 // Fix #12392 for oldIE
5706 while ( tmp.firstChild ) {
5707 tmp.removeChild( tmp.firstChild );
5708 }
5709
5710 // Remember the top-level container for proper cleanup
5711 tmp = safe.lastChild;
5712 }
5713 }
5714 }
5715
5716 // Fix #11356: Clear elements from fragment
5717 if ( tmp ) {
5718 safe.removeChild( tmp );
5719 }
5720
5721 // Reset defaultChecked for any radios and checkboxes
5722 // about to be appended to the DOM in IE 6/7 (#8060)
5723 if ( !support.appendChecked ) {
5724 jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
5725 }
5726
5727 i = 0;
5728 while ( (elem = nodes[ i++ ]) ) {
5729
5730 // #4087 - If origin and destination elements are the same, and this is
5731 // that element, do not do anything
5732 if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
5733 continue;
5734 }
5735
5736 contains = jQuery.contains( elem.ownerDocument, elem );
5737
5738 // Append to fragment
5739 tmp = getAll( safe.appendChild( elem ), "script" );
5740
5741 // Preserve script evaluation history
5742 if ( contains ) {
5743 setGlobalEval( tmp );
5744 }
5745
5746 // Capture executables
5747 if ( scripts ) {
5748 j = 0;
5749 while ( (elem = tmp[ j++ ]) ) {
5750 if ( rscriptType.test( elem.type || "" ) ) {
5751 scripts.push( elem );
5752 }
5753 }
5754 }
5755 }
5756
5757 tmp = null;
5758
5759 return safe;
5760 },
5761
5762 cleanData: function( elems, /* internal */ acceptData ) {
5763 var elem, type, id, data,
5764 i = 0,
5765 internalKey = jQuery.expando,
5766 cache = jQuery.cache,
5767 deleteExpando = support.deleteExpando,
5768 special = jQuery.event.special;
5769
5770 for ( ; (elem = elems[i]) != null; i++ ) {
5771 if ( acceptData || jQuery.acceptData( elem ) ) {
5772
5773 id = elem[ internalKey ];
5774 data = id && cache[ id ];
5775
5776 if ( data ) {
5777 if ( data.events ) {
5778 for ( type in data.events ) {
5779 if ( special[ type ] ) {
5780 jQuery.event.remove( elem, type );
5781
5782 // This is a shortcut to avoid jQuery.event.remove's overhead
5783 } else {
5784 jQuery.removeEvent( elem, type, data.handle );
5785 }
5786 }
5787 }
5788
5789 // Remove cache only if it was not already removed by jQuery.event.remove
5790 if ( cache[ id ] ) {
5791
5792 delete cache[ id ];
5793
5794 // IE does not allow us to delete expando properties from nodes,
5795 // nor does it have a removeAttribute function on Document nodes;
5796 // we must handle all of these cases
5797 if ( deleteExpando ) {
5798 delete elem[ internalKey ];
5799
5800 } else if ( typeof elem.removeAttribute !== strundefined ) {
5801 elem.removeAttribute( internalKey );
5802
5803 } else {
5804 elem[ internalKey ] = null;
5805 }
5806
5807 deletedIds.push( id );
5808 }
5809 }
5810 }
5811 }
5812 }
5813});
5814
5815jQuery.fn.extend({
5816 text: function( value ) {
5817 return access( this, function( value ) {
5818 return value === undefined ?
5819 jQuery.text( this ) :
5820 this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
5821 }, null, value, arguments.length );
5822 },
5823
5824 append: function() {
5825 return this.domManip( arguments, function( elem ) {
5826 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5827 var target = manipulationTarget( this, elem );
5828 target.appendChild( elem );
5829 }
5830 });
5831 },
5832
5833 prepend: function() {
5834 return this.domManip( arguments, function( elem ) {
5835 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5836 var target = manipulationTarget( this, elem );
5837 target.insertBefore( elem, target.firstChild );
5838 }
5839 });
5840 },
5841
5842 before: function() {
5843 return this.domManip( arguments, function( elem ) {
5844 if ( this.parentNode ) {
5845 this.parentNode.insertBefore( elem, this );
5846 }
5847 });
5848 },
5849
5850 after: function() {
5851 return this.domManip( arguments, function( elem ) {
5852 if ( this.parentNode ) {
5853 this.parentNode.insertBefore( elem, this.nextSibling );
5854 }
5855 });
5856 },
5857
5858 remove: function( selector, keepData /* Internal Use Only */ ) {
5859 var elem,
5860 elems = selector ? jQuery.filter( selector, this ) : this,
5861 i = 0;
5862
5863 for ( ; (elem = elems[i]) != null; i++ ) {
5864
5865 if ( !keepData && elem.nodeType === 1 ) {
5866 jQuery.cleanData( getAll( elem ) );
5867 }
5868
5869 if ( elem.parentNode ) {
5870 if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
5871 setGlobalEval( getAll( elem, "script" ) );
5872 }
5873 elem.parentNode.removeChild( elem );
5874 }
5875 }
5876
5877 return this;
5878 },
5879
5880 empty: function() {
5881 var elem,
5882 i = 0;
5883
5884 for ( ; (elem = this[i]) != null; i++ ) {
5885 // Remove element nodes and prevent memory leaks
5886 if ( elem.nodeType === 1 ) {
5887 jQuery.cleanData( getAll( elem, false ) );
5888 }
5889
5890 // Remove any remaining nodes
5891 while ( elem.firstChild ) {
5892 elem.removeChild( elem.firstChild );
5893 }
5894
5895 // If this is a select, ensure that it displays empty (#12336)
5896 // Support: IE<9
5897 if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
5898 elem.options.length = 0;
5899 }
5900 }
5901
5902 return this;
5903 },
5904
5905 clone: function( dataAndEvents, deepDataAndEvents ) {
5906 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
5907 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
5908
5909 return this.map(function() {
5910 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
5911 });
5912 },
5913
5914 html: function( value ) {
5915 return access( this, function( value ) {
5916 var elem = this[ 0 ] || {},
5917 i = 0,
5918 l = this.length;
5919
5920 if ( value === undefined ) {
5921 return elem.nodeType === 1 ?
5922 elem.innerHTML.replace( rinlinejQuery, "" ) :
5923 undefined;
5924 }
5925
5926 // See if we can take a shortcut and just use innerHTML
5927 if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
5928 ( support.htmlSerialize || !rnoshimcache.test( value ) ) &&
5929 ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
5930 !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
5931
5932 value = value.replace( rxhtmlTag, "<$1></$2>" );
5933
5934 try {
5935 for (; i < l; i++ ) {
5936 // Remove element nodes and prevent memory leaks
5937 elem = this[i] || {};
5938 if ( elem.nodeType === 1 ) {
5939 jQuery.cleanData( getAll( elem, false ) );
5940 elem.innerHTML = value;
5941 }
5942 }
5943
5944 elem = 0;
5945
5946 // If using innerHTML throws an exception, use the fallback method
5947 } catch(e) {}
5948 }
5949
5950 if ( elem ) {
5951 this.empty().append( value );
5952 }
5953 }, null, value, arguments.length );
5954 },
5955
5956 replaceWith: function() {
5957 var arg = arguments[ 0 ];
5958
5959 // Make the changes, replacing each context element with the new content
5960 this.domManip( arguments, function( elem ) {
5961 arg = this.parentNode;
5962
5963 jQuery.cleanData( getAll( this ) );
5964
5965 if ( arg ) {
5966 arg.replaceChild( elem, this );
5967 }
5968 });
5969
5970 // Force removal if there was no new content (e.g., from empty arguments)
5971 return arg && (arg.length || arg.nodeType) ? this : this.remove();
5972 },
5973
5974 detach: function( selector ) {
5975 return this.remove( selector, true );
5976 },
5977
5978 domManip: function( args, callback ) {
5979
5980 // Flatten any nested arrays
5981 args = concat.apply( [], args );
5982
5983 var first, node, hasScripts,
5984 scripts, doc, fragment,
5985 i = 0,
5986 l = this.length,
5987 set = this,
5988 iNoClone = l - 1,
5989 value = args[0],
5990 isFunction = jQuery.isFunction( value );
5991
5992 // We can't cloneNode fragments that contain checked, in WebKit
5993 if ( isFunction ||
5994 ( l > 1 && typeof value === "string" &&
5995 !support.checkClone && rchecked.test( value ) ) ) {
5996 return this.each(function( index ) {
5997 var self = set.eq( index );
5998 if ( isFunction ) {
5999 args[0] = value.call( this, index, self.html() );
6000 }
6001 self.domManip( args, callback );
6002 });
6003 }
6004
6005 if ( l ) {
6006 fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
6007 first = fragment.firstChild;
6008
6009 if ( fragment.childNodes.length === 1 ) {
6010 fragment = first;
6011 }
6012
6013 if ( first ) {
6014 scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
6015 hasScripts = scripts.length;
6016
6017 // Use the original fragment for the last item instead of the first because it can end up
6018 // being emptied incorrectly in certain situations (#8070).
6019 for ( ; i < l; i++ ) {
6020 node = fragment;
6021
6022 if ( i !== iNoClone ) {
6023 node = jQuery.clone( node, true, true );
6024
6025 // Keep references to cloned scripts for later restoration
6026 if ( hasScripts ) {
6027 jQuery.merge( scripts, getAll( node, "script" ) );
6028 }
6029 }
6030
6031 callback.call( this[i], node, i );
6032 }
6033
6034 if ( hasScripts ) {
6035 doc = scripts[ scripts.length - 1 ].ownerDocument;
6036
6037 // Reenable scripts
6038 jQuery.map( scripts, restoreScript );
6039
6040 // Evaluate executable scripts on first document insertion
6041 for ( i = 0; i < hasScripts; i++ ) {
6042 node = scripts[ i ];
6043 if ( rscriptType.test( node.type || "" ) &&
6044 !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
6045
6046 if ( node.src ) {
6047 // Optional AJAX dependency, but won't run scripts if not present
6048 if ( jQuery._evalUrl ) {
6049 jQuery._evalUrl( node.src );
6050 }
6051 } else {
6052 jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
6053 }
6054 }
6055 }
6056 }
6057
6058 // Fix #11809: Avoid leaking memory
6059 fragment = first = null;
6060 }
6061 }
6062
6063 return this;
6064 }
6065});
6066
6067jQuery.each({
6068 appendTo: "append",
6069 prependTo: "prepend",
6070 insertBefore: "before",
6071 insertAfter: "after",
6072 replaceAll: "replaceWith"
6073}, function( name, original ) {
6074 jQuery.fn[ name ] = function( selector ) {
6075 var elems,
6076 i = 0,
6077 ret = [],
6078 insert = jQuery( selector ),
6079 last = insert.length - 1;
6080
6081 for ( ; i <= last; i++ ) {
6082 elems = i === last ? this : this.clone(true);
6083 jQuery( insert[i] )[ original ]( elems );
6084
6085 // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
6086 push.apply( ret, elems.get() );
6087 }
6088
6089 return this.pushStack( ret );
6090 };
6091});
6092
6093
6094var iframe,
6095 elemdisplay = {};
6096
6097/**
6098 * Retrieve the actual display of a element
6099 * @param {String} name nodeName of the element
6100 * @param {Object} doc Document object
6101 */
6102// Called only from within defaultDisplay
6103function actualDisplay( name, doc ) {
6104 var style,
6105 elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
6106
6107 // getDefaultComputedStyle might be reliably used only on attached element
6108 display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
6109
6110 // Use of this method is a temporary fix (more like optmization) until something better comes along,
6111 // since it was removed from specification and supported only in FF
6112 style.display : jQuery.css( elem[ 0 ], "display" );
6113
6114 // We don't have any data stored on the element,
6115 // so use "detach" method as fast way to get rid of the element
6116 elem.detach();
6117
6118 return display;
6119}
6120
6121/**
6122 * Try to determine the default display value of an element
6123 * @param {String} nodeName
6124 */
6125function defaultDisplay( nodeName ) {
6126 var doc = document,
6127 display = elemdisplay[ nodeName ];
6128
6129 if ( !display ) {
6130 display = actualDisplay( nodeName, doc );
6131
6132 // If the simple way fails, read from inside an iframe
6133 if ( display === "none" || !display ) {
6134
6135 // Use the already-created iframe if possible
6136 iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
6137
6138 // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
6139 doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
6140
6141 // Support: IE
6142 doc.write();
6143 doc.close();
6144
6145 display = actualDisplay( nodeName, doc );
6146 iframe.detach();
6147 }
6148
6149 // Store the correct default display
6150 elemdisplay[ nodeName ] = display;
6151 }
6152
6153 return display;
6154}
6155
6156
6157(function() {
6158 var shrinkWrapBlocksVal;
6159
6160 support.shrinkWrapBlocks = function() {
6161 if ( shrinkWrapBlocksVal != null ) {
6162 return shrinkWrapBlocksVal;
6163 }
6164
6165 // Will be changed later if needed.
6166 shrinkWrapBlocksVal = false;
6167
6168 // Minified: var b,c,d
6169 var div, body, container;
6170
6171 body = document.getElementsByTagName( "body" )[ 0 ];
6172 if ( !body || !body.style ) {
6173 // Test fired too early or in an unsupported environment, exit.
6174 return;
6175 }
6176
6177 // Setup
6178 div = document.createElement( "div" );
6179 container = document.createElement( "div" );
6180 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
6181 body.appendChild( container ).appendChild( div );
6182
6183 // Support: IE6
6184 // Check if elements with layout shrink-wrap their children
6185 if ( typeof div.style.zoom !== strundefined ) {
6186 // Reset CSS: box-sizing; display; margin; border
6187 div.style.cssText =
6188 // Support: Firefox<29, Android 2.3
6189 // Vendor-prefix box-sizing
6190 "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
6191 "box-sizing:content-box;display:block;margin:0;border:0;" +
6192 "padding:1px;width:1px;zoom:1";
6193 div.appendChild( document.createElement( "div" ) ).style.width = "5px";
6194 shrinkWrapBlocksVal = div.offsetWidth !== 3;
6195 }
6196
6197 body.removeChild( container );
6198
6199 return shrinkWrapBlocksVal;
6200 };
6201
6202})();
6203var rmargin = (/^margin/);
6204
6205var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
6206
6207
6208
6209var getStyles, curCSS,
6210 rposition = /^(top|right|bottom|left)$/;
6211
6212if ( window.getComputedStyle ) {
6213 getStyles = function( elem ) {
6214 return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
6215 };
6216
6217 curCSS = function( elem, name, computed ) {
6218 var width, minWidth, maxWidth, ret,
6219 style = elem.style;
6220
6221 computed = computed || getStyles( elem );
6222
6223 // getPropertyValue is only needed for .css('filter') in IE9, see #12537
6224 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
6225
6226 if ( computed ) {
6227
6228 if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
6229 ret = jQuery.style( elem, name );
6230 }
6231
6232 // A tribute to the "awesome hack by Dean Edwards"
6233 // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
6234 // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
6235 // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
6236 if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
6237
6238 // Remember the original values
6239 width = style.width;
6240 minWidth = style.minWidth;
6241 maxWidth = style.maxWidth;
6242
6243 // Put in the new values to get a computed value out
6244 style.minWidth = style.maxWidth = style.width = ret;
6245 ret = computed.width;
6246
6247 // Revert the changed values
6248 style.width = width;
6249 style.minWidth = minWidth;
6250 style.maxWidth = maxWidth;
6251 }
6252 }
6253
6254 // Support: IE
6255 // IE returns zIndex value as an integer.
6256 return ret === undefined ?
6257 ret :
6258 ret + "";
6259 };
6260} else if ( document.documentElement.currentStyle ) {
6261 getStyles = function( elem ) {
6262 return elem.currentStyle;
6263 };
6264
6265 curCSS = function( elem, name, computed ) {
6266 var left, rs, rsLeft, ret,
6267 style = elem.style;
6268
6269 computed = computed || getStyles( elem );
6270 ret = computed ? computed[ name ] : undefined;
6271
6272 // Avoid setting ret to empty string here
6273 // so we don't default to auto
6274 if ( ret == null && style && style[ name ] ) {
6275 ret = style[ name ];
6276 }
6277
6278 // From the awesome hack by Dean Edwards
6279 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
6280
6281 // If we're not dealing with a regular pixel number
6282 // but a number that has a weird ending, we need to convert it to pixels
6283 // but not position css attributes, as those are proportional to the parent element instead
6284 // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
6285 if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
6286
6287 // Remember the original values
6288 left = style.left;
6289 rs = elem.runtimeStyle;
6290 rsLeft = rs && rs.left;
6291
6292 // Put in the new values to get a computed value out
6293 if ( rsLeft ) {
6294 rs.left = elem.currentStyle.left;
6295 }
6296 style.left = name === "fontSize" ? "1em" : ret;
6297 ret = style.pixelLeft + "px";
6298
6299 // Revert the changed values
6300 style.left = left;
6301 if ( rsLeft ) {
6302 rs.left = rsLeft;
6303 }
6304 }
6305
6306 // Support: IE
6307 // IE returns zIndex value as an integer.
6308 return ret === undefined ?
6309 ret :
6310 ret + "" || "auto";
6311 };
6312}
6313
6314
6315
6316
6317function addGetHookIf( conditionFn, hookFn ) {
6318 // Define the hook, we'll check on the first run if it's really needed.
6319 return {
6320 get: function() {
6321 var condition = conditionFn();
6322
6323 if ( condition == null ) {
6324 // The test was not ready at this point; screw the hook this time
6325 // but check again when needed next time.
6326 return;
6327 }
6328
6329 if ( condition ) {
6330 // Hook not needed (or it's not possible to use it due to missing dependency),
6331 // remove it.
6332 // Since there are no other hooks for marginRight, remove the whole object.
6333 delete this.get;
6334 return;
6335 }
6336
6337 // Hook needed; redefine it so that the support test is not executed again.
6338
6339 return (this.get = hookFn).apply( this, arguments );
6340 }
6341 };
6342}
6343
6344
6345(function() {
6346 // Minified: var b,c,d,e,f,g, h,i
6347 var div, style, a, pixelPositionVal, boxSizingReliableVal,
6348 reliableHiddenOffsetsVal, reliableMarginRightVal;
6349
6350 // Setup
6351 div = document.createElement( "div" );
6352 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
6353 a = div.getElementsByTagName( "a" )[ 0 ];
6354 style = a && a.style;
6355
6356 // Finish early in limited (non-browser) environments
6357 if ( !style ) {
6358 return;
6359 }
6360
6361 style.cssText = "float:left;opacity:.5";
6362
6363 // Support: IE<9
6364 // Make sure that element opacity exists (as opposed to filter)
6365 support.opacity = style.opacity === "0.5";
6366
6367 // Verify style float existence
6368 // (IE uses styleFloat instead of cssFloat)
6369 support.cssFloat = !!style.cssFloat;
6370
6371 div.style.backgroundClip = "content-box";
6372 div.cloneNode( true ).style.backgroundClip = "";
6373 support.clearCloneStyle = div.style.backgroundClip === "content-box";
6374
6375 // Support: Firefox<29, Android 2.3
6376 // Vendor-prefix box-sizing
6377 support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
6378 style.WebkitBoxSizing === "";
6379
6380 jQuery.extend(support, {
6381 reliableHiddenOffsets: function() {
6382 if ( reliableHiddenOffsetsVal == null ) {
6383 computeStyleTests();
6384 }
6385 return reliableHiddenOffsetsVal;
6386 },
6387
6388 boxSizingReliable: function() {
6389 if ( boxSizingReliableVal == null ) {
6390 computeStyleTests();
6391 }
6392 return boxSizingReliableVal;
6393 },
6394
6395 pixelPosition: function() {
6396 if ( pixelPositionVal == null ) {
6397 computeStyleTests();
6398 }
6399 return pixelPositionVal;
6400 },
6401
6402 // Support: Android 2.3
6403 reliableMarginRight: function() {
6404 if ( reliableMarginRightVal == null ) {
6405 computeStyleTests();
6406 }
6407 return reliableMarginRightVal;
6408 }
6409 });
6410
6411 function computeStyleTests() {
6412 // Minified: var b,c,d,j
6413 var div, body, container, contents;
6414
6415 body = document.getElementsByTagName( "body" )[ 0 ];
6416 if ( !body || !body.style ) {
6417 // Test fired too early or in an unsupported environment, exit.
6418 return;
6419 }
6420
6421 // Setup
6422 div = document.createElement( "div" );
6423 container = document.createElement( "div" );
6424 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
6425 body.appendChild( container ).appendChild( div );
6426
6427 div.style.cssText =
6428 // Support: Firefox<29, Android 2.3
6429 // Vendor-prefix box-sizing
6430 "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
6431 "box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
6432 "border:1px;padding:1px;width:4px;position:absolute";
6433
6434 // Support: IE<9
6435 // Assume reasonable values in the absence of getComputedStyle
6436 pixelPositionVal = boxSizingReliableVal = false;
6437 reliableMarginRightVal = true;
6438
6439 // Check for getComputedStyle so that this code is not run in IE<9.
6440 if ( window.getComputedStyle ) {
6441 pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
6442 boxSizingReliableVal =
6443 ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
6444
6445 // Support: Android 2.3
6446 // Div with explicit width and no margin-right incorrectly
6447 // gets computed margin-right based on width of container (#3333)
6448 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
6449 contents = div.appendChild( document.createElement( "div" ) );
6450
6451 // Reset CSS: box-sizing; display; margin; border; padding
6452 contents.style.cssText = div.style.cssText =
6453 // Support: Firefox<29, Android 2.3
6454 // Vendor-prefix box-sizing
6455 "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
6456 "box-sizing:content-box;display:block;margin:0;border:0;padding:0";
6457 contents.style.marginRight = contents.style.width = "0";
6458 div.style.width = "1px";
6459
6460 reliableMarginRightVal =
6461 !parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
6462 }
6463
6464 // Support: IE8
6465 // Check if table cells still have offsetWidth/Height when they are set
6466 // to display:none and there are still other visible table cells in a
6467 // table row; if so, offsetWidth/Height are not reliable for use when
6468 // determining if an element has been hidden directly using
6469 // display:none (it is still safe to use offsets if a parent element is
6470 // hidden; don safety goggles and see bug #4512 for more information).
6471 div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
6472 contents = div.getElementsByTagName( "td" );
6473 contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
6474 reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
6475 if ( reliableHiddenOffsetsVal ) {
6476 contents[ 0 ].style.display = "";
6477 contents[ 1 ].style.display = "none";
6478 reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
6479 }
6480
6481 body.removeChild( container );
6482 }
6483
6484})();
6485
6486
6487// A method for quickly swapping in/out CSS properties to get correct calculations.
6488jQuery.swap = function( elem, options, callback, args ) {
6489 var ret, name,
6490 old = {};
6491
6492 // Remember the old values, and insert the new ones
6493 for ( name in options ) {
6494 old[ name ] = elem.style[ name ];
6495 elem.style[ name ] = options[ name ];
6496 }
6497
6498 ret = callback.apply( elem, args || [] );
6499
6500 // Revert the old values
6501 for ( name in options ) {
6502 elem.style[ name ] = old[ name ];
6503 }
6504
6505 return ret;
6506};
6507
6508
6509var
6510 ralpha = /alpha\([^)]*\)/i,
6511 ropacity = /opacity\s*=\s*([^)]*)/,
6512
6513 // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
6514 // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6515 rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6516 rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
6517 rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
6518
6519 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6520 cssNormalTransform = {
6521 letterSpacing: "0",
6522 fontWeight: "400"
6523 },
6524
6525 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
6526
6527
6528// return a css property mapped to a potentially vendor prefixed property
6529function vendorPropName( style, name ) {
6530
6531 // shortcut for names that are not vendor prefixed
6532 if ( name in style ) {
6533 return name;
6534 }
6535
6536 // check for vendor prefixed names
6537 var capName = name.charAt(0).toUpperCase() + name.slice(1),
6538 origName = name,
6539 i = cssPrefixes.length;
6540
6541 while ( i-- ) {
6542 name = cssPrefixes[ i ] + capName;
6543 if ( name in style ) {
6544 return name;
6545 }
6546 }
6547
6548 return origName;
6549}
6550
6551function showHide( elements, show ) {
6552 var display, elem, hidden,
6553 values = [],
6554 index = 0,
6555 length = elements.length;
6556
6557 for ( ; index < length; index++ ) {
6558 elem = elements[ index ];
6559 if ( !elem.style ) {
6560 continue;
6561 }
6562
6563 values[ index ] = jQuery._data( elem, "olddisplay" );
6564 display = elem.style.display;
6565 if ( show ) {
6566 // Reset the inline display of this element to learn if it is
6567 // being hidden by cascaded rules or not
6568 if ( !values[ index ] && display === "none" ) {
6569 elem.style.display = "";
6570 }
6571
6572 // Set elements which have been overridden with display: none
6573 // in a stylesheet to whatever the default browser style is
6574 // for such an element
6575 if ( elem.style.display === "" && isHidden( elem ) ) {
6576 values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
6577 }
6578 } else {
6579 hidden = isHidden( elem );
6580
6581 if ( display && display !== "none" || !hidden ) {
6582 jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
6583 }
6584 }
6585 }
6586
6587 // Set the display of most of the elements in a second loop
6588 // to avoid the constant reflow
6589 for ( index = 0; index < length; index++ ) {
6590 elem = elements[ index ];
6591 if ( !elem.style ) {
6592 continue;
6593 }
6594 if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6595 elem.style.display = show ? values[ index ] || "" : "none";
6596 }
6597 }
6598
6599 return elements;
6600}
6601
6602function setPositiveNumber( elem, value, subtract ) {
6603 var matches = rnumsplit.exec( value );
6604 return matches ?
6605 // Guard against undefined "subtract", e.g., when used as in cssHooks
6606 Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
6607 value;
6608}
6609
6610function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
6611 var i = extra === ( isBorderBox ? "border" : "content" ) ?
6612 // If we already have the right measurement, avoid augmentation
6613 4 :
6614 // Otherwise initialize for horizontal or vertical properties
6615 name === "width" ? 1 : 0,
6616
6617 val = 0;
6618
6619 for ( ; i < 4; i += 2 ) {
6620 // both box models exclude margin, so add it if we want it
6621 if ( extra === "margin" ) {
6622 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
6623 }
6624
6625 if ( isBorderBox ) {
6626 // border-box includes padding, so remove it if we want content
6627 if ( extra === "content" ) {
6628 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6629 }
6630
6631 // at this point, extra isn't border nor margin, so remove border
6632 if ( extra !== "margin" ) {
6633 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6634 }
6635 } else {
6636 // at this point, extra isn't content, so add padding
6637 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6638
6639 // at this point, extra isn't content nor padding, so add border
6640 if ( extra !== "padding" ) {
6641 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6642 }
6643 }
6644 }
6645
6646 return val;
6647}
6648
6649function getWidthOrHeight( elem, name, extra ) {
6650
6651 // Start with offset property, which is equivalent to the border-box value
6652 var valueIsBorderBox = true,
6653 val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
6654 styles = getStyles( elem ),
6655 isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
6656
6657 // some non-html elements return undefined for offsetWidth, so check for null/undefined
6658 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
6659 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
6660 if ( val <= 0 || val == null ) {
6661 // Fall back to computed then uncomputed css if necessary
6662 val = curCSS( elem, name, styles );
6663 if ( val < 0 || val == null ) {
6664 val = elem.style[ name ];
6665 }
6666
6667 // Computed unit is not pixels. Stop here and return.
6668 if ( rnumnonpx.test(val) ) {
6669 return val;
6670 }
6671
6672 // we need the check for style in case a browser which returns unreliable values
6673 // for getComputedStyle silently falls back to the reliable elem.style
6674 valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
6675
6676 // Normalize "", auto, and prepare for extra
6677 val = parseFloat( val ) || 0;
6678 }
6679
6680 // use the active box-sizing model to add/subtract irrelevant styles
6681 return ( val +
6682 augmentWidthOrHeight(
6683 elem,
6684 name,
6685 extra || ( isBorderBox ? "border" : "content" ),
6686 valueIsBorderBox,
6687 styles
6688 )
6689 ) + "px";
6690}
6691
6692jQuery.extend({
6693 // Add in style property hooks for overriding the default
6694 // behavior of getting and setting a style property
6695 cssHooks: {
6696 opacity: {
6697 get: function( elem, computed ) {
6698 if ( computed ) {
6699 // We should always get a number back from opacity
6700 var ret = curCSS( elem, "opacity" );
6701 return ret === "" ? "1" : ret;
6702 }
6703 }
6704 }
6705 },
6706
6707 // Don't automatically add "px" to these possibly-unitless properties
6708 cssNumber: {
6709 "columnCount": true,
6710 "fillOpacity": true,
6711 "flexGrow": true,
6712 "flexShrink": true,
6713 "fontWeight": true,
6714 "lineHeight": true,
6715 "opacity": true,
6716 "order": true,
6717 "orphans": true,
6718 "widows": true,
6719 "zIndex": true,
6720 "zoom": true
6721 },
6722
6723 // Add in properties whose names you wish to fix before
6724 // setting or getting the value
6725 cssProps: {
6726 // normalize float css property
6727 "float": support.cssFloat ? "cssFloat" : "styleFloat"
6728 },
6729
6730 // Get and set the style property on a DOM Node
6731 style: function( elem, name, value, extra ) {
6732 // Don't set styles on text and comment nodes
6733 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6734 return;
6735 }
6736
6737 // Make sure that we're working with the right name
6738 var ret, type, hooks,
6739 origName = jQuery.camelCase( name ),
6740 style = elem.style;
6741
6742 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
6743
6744 // gets hook for the prefixed version
6745 // followed by the unprefixed version
6746 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6747
6748 // Check if we're setting a value
6749 if ( value !== undefined ) {
6750 type = typeof value;
6751
6752 // convert relative number strings (+= or -=) to relative numbers. #7345
6753 if ( type === "string" && (ret = rrelNum.exec( value )) ) {
6754 value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
6755 // Fixes bug #9237
6756 type = "number";
6757 }
6758
6759 // Make sure that null and NaN values aren't set. See: #7116
6760 if ( value == null || value !== value ) {
6761 return;
6762 }
6763
6764 // If a number was passed in, add 'px' to the (except for certain CSS properties)
6765 if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
6766 value += "px";
6767 }
6768
6769 // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
6770 // but it would mean to define eight (for every problematic property) identical functions
6771 if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
6772 style[ name ] = "inherit";
6773 }
6774
6775 // If a hook was provided, use that value, otherwise just set the specified value
6776 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
6777
6778 // Support: IE
6779 // Swallow errors from 'invalid' CSS values (#5509)
6780 try {
6781 style[ name ] = value;
6782 } catch(e) {}
6783 }
6784
6785 } else {
6786 // If a hook was provided get the non-computed value from there
6787 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6788 return ret;
6789 }
6790
6791 // Otherwise just get the value from the style object
6792 return style[ name ];
6793 }
6794 },
6795
6796 css: function( elem, name, extra, styles ) {
6797 var num, val, hooks,
6798 origName = jQuery.camelCase( name );
6799
6800 // Make sure that we're working with the right name
6801 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
6802
6803 // gets hook for the prefixed version
6804 // followed by the unprefixed version
6805 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6806
6807 // If a hook was provided get the computed value from there
6808 if ( hooks && "get" in hooks ) {
6809 val = hooks.get( elem, true, extra );
6810 }
6811
6812 // Otherwise, if a way to get the computed value exists, use that
6813 if ( val === undefined ) {
6814 val = curCSS( elem, name, styles );
6815 }
6816
6817 //convert "normal" to computed value
6818 if ( val === "normal" && name in cssNormalTransform ) {
6819 val = cssNormalTransform[ name ];
6820 }
6821
6822 // Return, converting to number if forced or a qualifier was provided and val looks numeric
6823 if ( extra === "" || extra ) {
6824 num = parseFloat( val );
6825 return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
6826 }
6827 return val;
6828 }
6829});
6830
6831jQuery.each([ "height", "width" ], function( i, name ) {
6832 jQuery.cssHooks[ name ] = {
6833 get: function( elem, computed, extra ) {
6834 if ( computed ) {
6835 // certain elements can have dimension info if we invisibly show them
6836 // however, it must have a current display style that would benefit from this
6837 return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
6838 jQuery.swap( elem, cssShow, function() {
6839 return getWidthOrHeight( elem, name, extra );
6840 }) :
6841 getWidthOrHeight( elem, name, extra );
6842 }
6843 },
6844
6845 set: function( elem, value, extra ) {
6846 var styles = extra && getStyles( elem );
6847 return setPositiveNumber( elem, value, extra ?
6848 augmentWidthOrHeight(
6849 elem,
6850 name,
6851 extra,
6852 support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6853 styles
6854 ) : 0
6855 );
6856 }
6857 };
6858});
6859
6860if ( !support.opacity ) {
6861 jQuery.cssHooks.opacity = {
6862 get: function( elem, computed ) {
6863 // IE uses filters for opacity
6864 return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
6865 ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
6866 computed ? "1" : "";
6867 },
6868
6869 set: function( elem, value ) {
6870 var style = elem.style,
6871 currentStyle = elem.currentStyle,
6872 opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
6873 filter = currentStyle && currentStyle.filter || style.filter || "";
6874
6875 // IE has trouble with opacity if it does not have layout
6876 // Force it by setting the zoom level
6877 style.zoom = 1;
6878
6879 // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
6880 // if value === "", then remove inline opacity #12685
6881 if ( ( value >= 1 || value === "" ) &&
6882 jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
6883 style.removeAttribute ) {
6884
6885 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
6886 // if "filter:" is present at all, clearType is disabled, we want to avoid this
6887 // style.removeAttribute is IE Only, but so apparently is this code path...
6888 style.removeAttribute( "filter" );
6889
6890 // if there is no filter style applied in a css rule or unset inline opacity, we are done
6891 if ( value === "" || currentStyle && !currentStyle.filter ) {
6892 return;
6893 }
6894 }
6895
6896 // otherwise, set new filter values
6897 style.filter = ralpha.test( filter ) ?
6898 filter.replace( ralpha, opacity ) :
6899 filter + " " + opacity;
6900 }
6901 };
6902}
6903
6904jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
6905 function( elem, computed ) {
6906 if ( computed ) {
6907 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
6908 // Work around by temporarily setting element display to inline-block
6909 return jQuery.swap( elem, { "display": "inline-block" },
6910 curCSS, [ elem, "marginRight" ] );
6911 }
6912 }
6913);
6914
6915// These hooks are used by animate to expand properties
6916jQuery.each({
6917 margin: "",
6918 padding: "",
6919 border: "Width"
6920}, function( prefix, suffix ) {
6921 jQuery.cssHooks[ prefix + suffix ] = {
6922 expand: function( value ) {
6923 var i = 0,
6924 expanded = {},
6925
6926 // assumes a single number if not a string
6927 parts = typeof value === "string" ? value.split(" ") : [ value ];
6928
6929 for ( ; i < 4; i++ ) {
6930 expanded[ prefix + cssExpand[ i ] + suffix ] =
6931 parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
6932 }
6933
6934 return expanded;
6935 }
6936 };
6937
6938 if ( !rmargin.test( prefix ) ) {
6939 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
6940 }
6941});
6942
6943jQuery.fn.extend({
6944 css: function( name, value ) {
6945 return access( this, function( elem, name, value ) {
6946 var styles, len,
6947 map = {},
6948 i = 0;
6949
6950 if ( jQuery.isArray( name ) ) {
6951 styles = getStyles( elem );
6952 len = name.length;
6953
6954 for ( ; i < len; i++ ) {
6955 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6956 }
6957
6958 return map;
6959 }
6960
6961 return value !== undefined ?
6962 jQuery.style( elem, name, value ) :
6963 jQuery.css( elem, name );
6964 }, name, value, arguments.length > 1 );
6965 },
6966 show: function() {
6967 return showHide( this, true );
6968 },
6969 hide: function() {
6970 return showHide( this );
6971 },
6972 toggle: function( state ) {
6973 if ( typeof state === "boolean" ) {
6974 return state ? this.show() : this.hide();
6975 }
6976
6977 return this.each(function() {
6978 if ( isHidden( this ) ) {
6979 jQuery( this ).show();
6980 } else {
6981 jQuery( this ).hide();
6982 }
6983 });
6984 }
6985});
6986
6987
6988function Tween( elem, options, prop, end, easing ) {
6989 return new Tween.prototype.init( elem, options, prop, end, easing );
6990}
6991jQuery.Tween = Tween;
6992
6993Tween.prototype = {
6994 constructor: Tween,
6995 init: function( elem, options, prop, end, easing, unit ) {
6996 this.elem = elem;
6997 this.prop = prop;
6998 this.easing = easing || "swing";
6999 this.options = options;
7000 this.start = this.now = this.cur();
7001 this.end = end;
7002 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
7003 },
7004 cur: function() {
7005 var hooks = Tween.propHooks[ this.prop ];
7006
7007 return hooks && hooks.get ?
7008 hooks.get( this ) :
7009 Tween.propHooks._default.get( this );
7010 },
7011 run: function( percent ) {
7012 var eased,
7013 hooks = Tween.propHooks[ this.prop ];
7014
7015 if ( this.options.duration ) {
7016 this.pos = eased = jQuery.easing[ this.easing ](
7017 percent, this.options.duration * percent, 0, 1, this.options.duration
7018 );
7019 } else {
7020 this.pos = eased = percent;
7021 }
7022 this.now = ( this.end - this.start ) * eased + this.start;
7023
7024 if ( this.options.step ) {
7025 this.options.step.call( this.elem, this.now, this );
7026 }
7027
7028 if ( hooks && hooks.set ) {
7029 hooks.set( this );
7030 } else {
7031 Tween.propHooks._default.set( this );
7032 }
7033 return this;
7034 }
7035};
7036
7037Tween.prototype.init.prototype = Tween.prototype;
7038
7039Tween.propHooks = {
7040 _default: {
7041 get: function( tween ) {
7042 var result;
7043
7044 if ( tween.elem[ tween.prop ] != null &&
7045 (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
7046 return tween.elem[ tween.prop ];
7047 }
7048
7049 // passing an empty string as a 3rd parameter to .css will automatically
7050 // attempt a parseFloat and fallback to a string if the parse fails
7051 // so, simple values such as "10px" are parsed to Float.
7052 // complex values such as "rotate(1rad)" are returned as is.
7053 result = jQuery.css( tween.elem, tween.prop, "" );
7054 // Empty strings, null, undefined and "auto" are converted to 0.
7055 return !result || result === "auto" ? 0 : result;
7056 },
7057 set: function( tween ) {
7058 // use step hook for back compat - use cssHook if its there - use .style if its
7059 // available and use plain properties where available
7060 if ( jQuery.fx.step[ tween.prop ] ) {
7061 jQuery.fx.step[ tween.prop ]( tween );
7062 } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
7063 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
7064 } else {
7065 tween.elem[ tween.prop ] = tween.now;
7066 }
7067 }
7068 }
7069};
7070
7071// Support: IE <=9
7072// Panic based approach to setting things on disconnected nodes
7073
7074Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
7075 set: function( tween ) {
7076 if ( tween.elem.nodeType && tween.elem.parentNode ) {
7077 tween.elem[ tween.prop ] = tween.now;
7078 }
7079 }
7080};
7081
7082jQuery.easing = {
7083 linear: function( p ) {
7084 return p;
7085 },
7086 swing: function( p ) {
7087 return 0.5 - Math.cos( p * Math.PI ) / 2;
7088 }
7089};
7090
7091jQuery.fx = Tween.prototype.init;
7092
7093// Back Compat <1.8 extension point
7094jQuery.fx.step = {};
7095
7096
7097
7098
7099var
7100 fxNow, timerId,
7101 rfxtypes = /^(?:toggle|show|hide)$/,
7102 rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
7103 rrun = /queueHooks$/,
7104 animationPrefilters = [ defaultPrefilter ],
7105 tweeners = {
7106 "*": [ function( prop, value ) {
7107 var tween = this.createTween( prop, value ),
7108 target = tween.cur(),
7109 parts = rfxnum.exec( value ),
7110 unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
7111
7112 // Starting value computation is required for potential unit mismatches
7113 start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
7114 rfxnum.exec( jQuery.css( tween.elem, prop ) ),
7115 scale = 1,
7116 maxIterations = 20;
7117
7118 if ( start && start[ 3 ] !== unit ) {
7119 // Trust units reported by jQuery.css
7120 unit = unit || start[ 3 ];
7121
7122 // Make sure we update the tween properties later on
7123 parts = parts || [];
7124
7125 // Iteratively approximate from a nonzero starting point
7126 start = +target || 1;
7127
7128 do {
7129 // If previous iteration zeroed out, double until we get *something*
7130 // Use a string for doubling factor so we don't accidentally see scale as unchanged below
7131 scale = scale || ".5";
7132
7133 // Adjust and apply
7134 start = start / scale;
7135 jQuery.style( tween.elem, prop, start + unit );
7136
7137 // Update scale, tolerating zero or NaN from tween.cur()
7138 // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
7139 } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
7140 }
7141
7142 // Update tween properties
7143 if ( parts ) {
7144 start = tween.start = +start || +target || 0;
7145 tween.unit = unit;
7146 // If a +=/-= token was provided, we're doing a relative animation
7147 tween.end = parts[ 1 ] ?
7148 start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
7149 +parts[ 2 ];
7150 }
7151
7152 return tween;
7153 } ]
7154 };
7155
7156// Animations created synchronously will run synchronously
7157function createFxNow() {
7158 setTimeout(function() {
7159 fxNow = undefined;
7160 });
7161 return ( fxNow = jQuery.now() );
7162}
7163
7164// Generate parameters to create a standard animation
7165function genFx( type, includeWidth ) {
7166 var which,
7167 attrs = { height: type },
7168 i = 0;
7169
7170 // if we include width, step value is 1 to do all cssExpand values,
7171 // if we don't include width, step value is 2 to skip over Left and Right
7172 includeWidth = includeWidth ? 1 : 0;
7173 for ( ; i < 4 ; i += 2 - includeWidth ) {
7174 which = cssExpand[ i ];
7175 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
7176 }
7177
7178 if ( includeWidth ) {
7179 attrs.opacity = attrs.width = type;
7180 }
7181
7182 return attrs;
7183}
7184
7185function createTween( value, prop, animation ) {
7186 var tween,
7187 collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
7188 index = 0,
7189 length = collection.length;
7190 for ( ; index < length; index++ ) {
7191 if ( (tween = collection[ index ].call( animation, prop, value )) ) {
7192
7193 // we're done with this property
7194 return tween;
7195 }
7196 }
7197}
7198
7199function defaultPrefilter( elem, props, opts ) {
7200 /* jshint validthis: true */
7201 var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
7202 anim = this,
7203 orig = {},
7204 style = elem.style,
7205 hidden = elem.nodeType && isHidden( elem ),
7206 dataShow = jQuery._data( elem, "fxshow" );
7207
7208 // handle queue: false promises
7209 if ( !opts.queue ) {
7210 hooks = jQuery._queueHooks( elem, "fx" );
7211 if ( hooks.unqueued == null ) {
7212 hooks.unqueued = 0;
7213 oldfire = hooks.empty.fire;
7214 hooks.empty.fire = function() {
7215 if ( !hooks.unqueued ) {
7216 oldfire();
7217 }
7218 };
7219 }
7220 hooks.unqueued++;
7221
7222 anim.always(function() {
7223 // doing this makes sure that the complete handler will be called
7224 // before this completes
7225 anim.always(function() {
7226 hooks.unqueued--;
7227 if ( !jQuery.queue( elem, "fx" ).length ) {
7228 hooks.empty.fire();
7229 }
7230 });
7231 });
7232 }
7233
7234 // height/width overflow pass
7235 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
7236 // Make sure that nothing sneaks out
7237 // Record all 3 overflow attributes because IE does not
7238 // change the overflow attribute when overflowX and
7239 // overflowY are set to the same value
7240 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
7241
7242 // Set display property to inline-block for height/width
7243 // animations on inline elements that are having width/height animated
7244 display = jQuery.css( elem, "display" );
7245
7246 // Test default display if display is currently "none"
7247 checkDisplay = display === "none" ?
7248 jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
7249
7250 if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
7251
7252 // inline-level elements accept inline-block;
7253 // block-level elements need to be inline with layout
7254 if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
7255 style.display = "inline-block";
7256 } else {
7257 style.zoom = 1;
7258 }
7259 }
7260 }
7261
7262 if ( opts.overflow ) {
7263 style.overflow = "hidden";
7264 if ( !support.shrinkWrapBlocks() ) {
7265 anim.always(function() {
7266 style.overflow = opts.overflow[ 0 ];
7267 style.overflowX = opts.overflow[ 1 ];
7268 style.overflowY = opts.overflow[ 2 ];
7269 });
7270 }
7271 }
7272
7273 // show/hide pass
7274 for ( prop in props ) {
7275 value = props[ prop ];
7276 if ( rfxtypes.exec( value ) ) {
7277 delete props[ prop ];
7278 toggle = toggle || value === "toggle";
7279 if ( value === ( hidden ? "hide" : "show" ) ) {
7280
7281 // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
7282 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
7283 hidden = true;
7284 } else {
7285 continue;
7286 }
7287 }
7288 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
7289
7290 // Any non-fx value stops us from restoring the original display value
7291 } else {
7292 display = undefined;
7293 }
7294 }
7295
7296 if ( !jQuery.isEmptyObject( orig ) ) {
7297 if ( dataShow ) {
7298 if ( "hidden" in dataShow ) {
7299 hidden = dataShow.hidden;
7300 }
7301 } else {
7302 dataShow = jQuery._data( elem, "fxshow", {} );
7303 }
7304
7305 // store state if its toggle - enables .stop().toggle() to "reverse"
7306 if ( toggle ) {
7307 dataShow.hidden = !hidden;
7308 }
7309 if ( hidden ) {
7310 jQuery( elem ).show();
7311 } else {
7312 anim.done(function() {
7313 jQuery( elem ).hide();
7314 });
7315 }
7316 anim.done(function() {
7317 var prop;
7318 jQuery._removeData( elem, "fxshow" );
7319 for ( prop in orig ) {
7320 jQuery.style( elem, prop, orig[ prop ] );
7321 }
7322 });
7323 for ( prop in orig ) {
7324 tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
7325
7326 if ( !( prop in dataShow ) ) {
7327 dataShow[ prop ] = tween.start;
7328 if ( hidden ) {
7329 tween.end = tween.start;
7330 tween.start = prop === "width" || prop === "height" ? 1 : 0;
7331 }
7332 }
7333 }
7334
7335 // If this is a noop like .hide().hide(), restore an overwritten display value
7336 } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
7337 style.display = display;
7338 }
7339}
7340
7341function propFilter( props, specialEasing ) {
7342 var index, name, easing, value, hooks;
7343
7344 // camelCase, specialEasing and expand cssHook pass
7345 for ( index in props ) {
7346 name = jQuery.camelCase( index );
7347 easing = specialEasing[ name ];
7348 value = props[ index ];
7349 if ( jQuery.isArray( value ) ) {
7350 easing = value[ 1 ];
7351 value = props[ index ] = value[ 0 ];
7352 }
7353
7354 if ( index !== name ) {
7355 props[ name ] = value;
7356 delete props[ index ];
7357 }
7358
7359 hooks = jQuery.cssHooks[ name ];
7360 if ( hooks && "expand" in hooks ) {
7361 value = hooks.expand( value );
7362 delete props[ name ];
7363
7364 // not quite $.extend, this wont overwrite keys already present.
7365 // also - reusing 'index' from above because we have the correct "name"
7366 for ( index in value ) {
7367 if ( !( index in props ) ) {
7368 props[ index ] = value[ index ];
7369 specialEasing[ index ] = easing;
7370 }
7371 }
7372 } else {
7373 specialEasing[ name ] = easing;
7374 }
7375 }
7376}
7377
7378function Animation( elem, properties, options ) {
7379 var result,
7380 stopped,
7381 index = 0,
7382 length = animationPrefilters.length,
7383 deferred = jQuery.Deferred().always( function() {
7384 // don't match elem in the :animated selector
7385 delete tick.elem;
7386 }),
7387 tick = function() {
7388 if ( stopped ) {
7389 return false;
7390 }
7391 var currentTime = fxNow || createFxNow(),
7392 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
7393 // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
7394 temp = remaining / animation.duration || 0,
7395 percent = 1 - temp,
7396 index = 0,
7397 length = animation.tweens.length;
7398
7399 for ( ; index < length ; index++ ) {
7400 animation.tweens[ index ].run( percent );
7401 }
7402
7403 deferred.notifyWith( elem, [ animation, percent, remaining ]);
7404
7405 if ( percent < 1 && length ) {
7406 return remaining;
7407 } else {
7408 deferred.resolveWith( elem, [ animation ] );
7409 return false;
7410 }
7411 },
7412 animation = deferred.promise({
7413 elem: elem,
7414 props: jQuery.extend( {}, properties ),
7415 opts: jQuery.extend( true, { specialEasing: {} }, options ),
7416 originalProperties: properties,
7417 originalOptions: options,
7418 startTime: fxNow || createFxNow(),
7419 duration: options.duration,
7420 tweens: [],
7421 createTween: function( prop, end ) {
7422 var tween = jQuery.Tween( elem, animation.opts, prop, end,
7423 animation.opts.specialEasing[ prop ] || animation.opts.easing );
7424 animation.tweens.push( tween );
7425 return tween;
7426 },
7427 stop: function( gotoEnd ) {
7428 var index = 0,
7429 // if we are going to the end, we want to run all the tweens
7430 // otherwise we skip this part
7431 length = gotoEnd ? animation.tweens.length : 0;
7432 if ( stopped ) {
7433 return this;
7434 }
7435 stopped = true;
7436 for ( ; index < length ; index++ ) {
7437 animation.tweens[ index ].run( 1 );
7438 }
7439
7440 // resolve when we played the last frame
7441 // otherwise, reject
7442 if ( gotoEnd ) {
7443 deferred.resolveWith( elem, [ animation, gotoEnd ] );
7444 } else {
7445 deferred.rejectWith( elem, [ animation, gotoEnd ] );
7446 }
7447 return this;
7448 }
7449 }),
7450 props = animation.props;
7451
7452 propFilter( props, animation.opts.specialEasing );
7453
7454 for ( ; index < length ; index++ ) {
7455 result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
7456 if ( result ) {
7457 return result;
7458 }
7459 }
7460
7461 jQuery.map( props, createTween, animation );
7462
7463 if ( jQuery.isFunction( animation.opts.start ) ) {
7464 animation.opts.start.call( elem, animation );
7465 }
7466
7467 jQuery.fx.timer(
7468 jQuery.extend( tick, {
7469 elem: elem,
7470 anim: animation,
7471 queue: animation.opts.queue
7472 })
7473 );
7474
7475 // attach callbacks from options
7476 return animation.progress( animation.opts.progress )
7477 .done( animation.opts.done, animation.opts.complete )
7478 .fail( animation.opts.fail )
7479 .always( animation.opts.always );
7480}
7481
7482jQuery.Animation = jQuery.extend( Animation, {
7483 tweener: function( props, callback ) {
7484 if ( jQuery.isFunction( props ) ) {
7485 callback = props;
7486 props = [ "*" ];
7487 } else {
7488 props = props.split(" ");
7489 }
7490
7491 var prop,
7492 index = 0,
7493 length = props.length;
7494
7495 for ( ; index < length ; index++ ) {
7496 prop = props[ index ];
7497 tweeners[ prop ] = tweeners[ prop ] || [];
7498 tweeners[ prop ].unshift( callback );
7499 }
7500 },
7501
7502 prefilter: function( callback, prepend ) {
7503 if ( prepend ) {
7504 animationPrefilters.unshift( callback );
7505 } else {
7506 animationPrefilters.push( callback );
7507 }
7508 }
7509});
7510
7511jQuery.speed = function( speed, easing, fn ) {
7512 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
7513 complete: fn || !fn && easing ||
7514 jQuery.isFunction( speed ) && speed,
7515 duration: speed,
7516 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
7517 };
7518
7519 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
7520 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
7521
7522 // normalize opt.queue - true/undefined/null -> "fx"
7523 if ( opt.queue == null || opt.queue === true ) {
7524 opt.queue = "fx";
7525 }
7526
7527 // Queueing
7528 opt.old = opt.complete;
7529
7530 opt.complete = function() {
7531 if ( jQuery.isFunction( opt.old ) ) {
7532 opt.old.call( this );
7533 }
7534
7535 if ( opt.queue ) {
7536 jQuery.dequeue( this, opt.queue );
7537 }
7538 };
7539
7540 return opt;
7541};
7542
7543jQuery.fn.extend({
7544 fadeTo: function( speed, to, easing, callback ) {
7545
7546 // show any hidden elements after setting opacity to 0
7547 return this.filter( isHidden ).css( "opacity", 0 ).show()
7548
7549 // animate to the value specified
7550 .end().animate({ opacity: to }, speed, easing, callback );
7551 },
7552 animate: function( prop, speed, easing, callback ) {
7553 var empty = jQuery.isEmptyObject( prop ),
7554 optall = jQuery.speed( speed, easing, callback ),
7555 doAnimation = function() {
7556 // Operate on a copy of prop so per-property easing won't be lost
7557 var anim = Animation( this, jQuery.extend( {}, prop ), optall );
7558
7559 // Empty animations, or finishing resolves immediately
7560 if ( empty || jQuery._data( this, "finish" ) ) {
7561 anim.stop( true );
7562 }
7563 };
7564 doAnimation.finish = doAnimation;
7565
7566 return empty || optall.queue === false ?
7567 this.each( doAnimation ) :
7568 this.queue( optall.queue, doAnimation );
7569 },
7570 stop: function( type, clearQueue, gotoEnd ) {
7571 var stopQueue = function( hooks ) {
7572 var stop = hooks.stop;
7573 delete hooks.stop;
7574 stop( gotoEnd );
7575 };
7576
7577 if ( typeof type !== "string" ) {
7578 gotoEnd = clearQueue;
7579 clearQueue = type;
7580 type = undefined;
7581 }
7582 if ( clearQueue && type !== false ) {
7583 this.queue( type || "fx", [] );
7584 }
7585
7586 return this.each(function() {
7587 var dequeue = true,
7588 index = type != null && type + "queueHooks",
7589 timers = jQuery.timers,
7590 data = jQuery._data( this );
7591
7592 if ( index ) {
7593 if ( data[ index ] && data[ index ].stop ) {
7594 stopQueue( data[ index ] );
7595 }
7596 } else {
7597 for ( index in data ) {
7598 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
7599 stopQueue( data[ index ] );
7600 }
7601 }
7602 }
7603
7604 for ( index = timers.length; index--; ) {
7605 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
7606 timers[ index ].anim.stop( gotoEnd );
7607 dequeue = false;
7608 timers.splice( index, 1 );
7609 }
7610 }
7611
7612 // start the next in the queue if the last step wasn't forced
7613 // timers currently will call their complete callbacks, which will dequeue
7614 // but only if they were gotoEnd
7615 if ( dequeue || !gotoEnd ) {
7616 jQuery.dequeue( this, type );
7617 }
7618 });
7619 },
7620 finish: function( type ) {
7621 if ( type !== false ) {
7622 type = type || "fx";
7623 }
7624 return this.each(function() {
7625 var index,
7626 data = jQuery._data( this ),
7627 queue = data[ type + "queue" ],
7628 hooks = data[ type + "queueHooks" ],
7629 timers = jQuery.timers,
7630 length = queue ? queue.length : 0;
7631
7632 // enable finishing flag on private data
7633 data.finish = true;
7634
7635 // empty the queue first
7636 jQuery.queue( this, type, [] );
7637
7638 if ( hooks && hooks.stop ) {
7639 hooks.stop.call( this, true );
7640 }
7641
7642 // look for any active animations, and finish them
7643 for ( index = timers.length; index--; ) {
7644 if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
7645 timers[ index ].anim.stop( true );
7646 timers.splice( index, 1 );
7647 }
7648 }
7649
7650 // look for any animations in the old queue and finish them
7651 for ( index = 0; index < length; index++ ) {
7652 if ( queue[ index ] && queue[ index ].finish ) {
7653 queue[ index ].finish.call( this );
7654 }
7655 }
7656
7657 // turn off finishing flag
7658 delete data.finish;
7659 });
7660 }
7661});
7662
7663jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
7664 var cssFn = jQuery.fn[ name ];
7665 jQuery.fn[ name ] = function( speed, easing, callback ) {
7666 return speed == null || typeof speed === "boolean" ?
7667 cssFn.apply( this, arguments ) :
7668 this.animate( genFx( name, true ), speed, easing, callback );
7669 };
7670});
7671
7672// Generate shortcuts for custom animations
7673jQuery.each({
7674 slideDown: genFx("show"),
7675 slideUp: genFx("hide"),
7676 slideToggle: genFx("toggle"),
7677 fadeIn: { opacity: "show" },
7678 fadeOut: { opacity: "hide" },
7679 fadeToggle: { opacity: "toggle" }
7680}, function( name, props ) {
7681 jQuery.fn[ name ] = function( speed, easing, callback ) {
7682 return this.animate( props, speed, easing, callback );
7683 };
7684});
7685
7686jQuery.timers = [];
7687jQuery.fx.tick = function() {
7688 var timer,
7689 timers = jQuery.timers,
7690 i = 0;
7691
7692 fxNow = jQuery.now();
7693
7694 for ( ; i < timers.length; i++ ) {
7695 timer = timers[ i ];
7696 // Checks the timer has not already been removed
7697 if ( !timer() && timers[ i ] === timer ) {
7698 timers.splice( i--, 1 );
7699 }
7700 }
7701
7702 if ( !timers.length ) {
7703 jQuery.fx.stop();
7704 }
7705 fxNow = undefined;
7706};
7707
7708jQuery.fx.timer = function( timer ) {
7709 jQuery.timers.push( timer );
7710 if ( timer() ) {
7711 jQuery.fx.start();
7712 } else {
7713 jQuery.timers.pop();
7714 }
7715};
7716
7717jQuery.fx.interval = 13;
7718
7719jQuery.fx.start = function() {
7720 if ( !timerId ) {
7721 timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
7722 }
7723};
7724
7725jQuery.fx.stop = function() {
7726 clearInterval( timerId );
7727 timerId = null;
7728};
7729
7730jQuery.fx.speeds = {
7731 slow: 600,
7732 fast: 200,
7733 // Default speed
7734 _default: 400
7735};
7736
7737
7738// Based off of the plugin by Clint Helfers, with permission.
7739// http://blindsignals.com/index.php/2009/07/jquery-delay/
7740jQuery.fn.delay = function( time, type ) {
7741 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
7742 type = type || "fx";
7743
7744 return this.queue( type, function( next, hooks ) {
7745 var timeout = setTimeout( next, time );
7746 hooks.stop = function() {
7747 clearTimeout( timeout );
7748 };
7749 });
7750};
7751
7752
7753(function() {
7754 // Minified: var a,b,c,d,e
7755 var input, div, select, a, opt;
7756
7757 // Setup
7758 div = document.createElement( "div" );
7759 div.setAttribute( "className", "t" );
7760 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
7761 a = div.getElementsByTagName("a")[ 0 ];
7762
7763 // First batch of tests.
7764 select = document.createElement("select");
7765 opt = select.appendChild( document.createElement("option") );
7766 input = div.getElementsByTagName("input")[ 0 ];
7767
7768 a.style.cssText = "top:1px";
7769
7770 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
7771 support.getSetAttribute = div.className !== "t";
7772
7773 // Get the style information from getAttribute
7774 // (IE uses .cssText instead)
7775 support.style = /top/.test( a.getAttribute("style") );
7776
7777 // Make sure that URLs aren't manipulated
7778 // (IE normalizes it by default)
7779 support.hrefNormalized = a.getAttribute("href") === "/a";
7780
7781 // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
7782 support.checkOn = !!input.value;
7783
7784 // Make sure that a selected-by-default option has a working selected property.
7785 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
7786 support.optSelected = opt.selected;
7787
7788 // Tests for enctype support on a form (#6743)
7789 support.enctype = !!document.createElement("form").enctype;
7790
7791 // Make sure that the options inside disabled selects aren't marked as disabled
7792 // (WebKit marks them as disabled)
7793 select.disabled = true;
7794 support.optDisabled = !opt.disabled;
7795
7796 // Support: IE8 only
7797 // Check if we can trust getAttribute("value")
7798 input = document.createElement( "input" );
7799 input.setAttribute( "value", "" );
7800 support.input = input.getAttribute( "value" ) === "";
7801
7802 // Check if an input maintains its value after becoming a radio
7803 input.value = "t";
7804 input.setAttribute( "type", "radio" );
7805 support.radioValue = input.value === "t";
7806})();
7807
7808
7809var rreturn = /\r/g;
7810
7811jQuery.fn.extend({
7812 val: function( value ) {
7813 var hooks, ret, isFunction,
7814 elem = this[0];
7815
7816 if ( !arguments.length ) {
7817 if ( elem ) {
7818 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
7819
7820 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
7821 return ret;
7822 }
7823
7824 ret = elem.value;
7825
7826 return typeof ret === "string" ?
7827 // handle most common string cases
7828 ret.replace(rreturn, "") :
7829 // handle cases where value is null/undef or number
7830 ret == null ? "" : ret;
7831 }
7832
7833 return;
7834 }
7835
7836 isFunction = jQuery.isFunction( value );
7837
7838 return this.each(function( i ) {
7839 var val;
7840
7841 if ( this.nodeType !== 1 ) {
7842 return;
7843 }
7844
7845 if ( isFunction ) {
7846 val = value.call( this, i, jQuery( this ).val() );
7847 } else {
7848 val = value;
7849 }
7850
7851 // Treat null/undefined as ""; convert numbers to string
7852 if ( val == null ) {
7853 val = "";
7854 } else if ( typeof val === "number" ) {
7855 val += "";
7856 } else if ( jQuery.isArray( val ) ) {
7857 val = jQuery.map( val, function( value ) {
7858 return value == null ? "" : value + "";
7859 });
7860 }
7861
7862 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
7863
7864 // If set returns undefined, fall back to normal setting
7865 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
7866 this.value = val;
7867 }
7868 });
7869 }
7870});
7871
7872jQuery.extend({
7873 valHooks: {
7874 option: {
7875 get: function( elem ) {
7876 var val = jQuery.find.attr( elem, "value" );
7877 return val != null ?
7878 val :
7879 // Support: IE10-11+
7880 // option.text throws exceptions (#14686, #14858)
7881 jQuery.trim( jQuery.text( elem ) );
7882 }
7883 },
7884 select: {
7885 get: function( elem ) {
7886 var value, option,
7887 options = elem.options,
7888 index = elem.selectedIndex,
7889 one = elem.type === "select-one" || index < 0,
7890 values = one ? null : [],
7891 max = one ? index + 1 : options.length,
7892 i = index < 0 ?
7893 max :
7894 one ? index : 0;
7895
7896 // Loop through all the selected options
7897 for ( ; i < max; i++ ) {
7898 option = options[ i ];
7899
7900 // oldIE doesn't update selected after form reset (#2551)
7901 if ( ( option.selected || i === index ) &&
7902 // Don't return options that are disabled or in a disabled optgroup
7903 ( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
7904 ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
7905
7906 // Get the specific value for the option
7907 value = jQuery( option ).val();
7908
7909 // We don't need an array for one selects
7910 if ( one ) {
7911 return value;
7912 }
7913
7914 // Multi-Selects return an array
7915 values.push( value );
7916 }
7917 }
7918
7919 return values;
7920 },
7921
7922 set: function( elem, value ) {
7923 var optionSet, option,
7924 options = elem.options,
7925 values = jQuery.makeArray( value ),
7926 i = options.length;
7927
7928 while ( i-- ) {
7929 option = options[ i ];
7930
7931 if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {
7932
7933 // Support: IE6
7934 // When new option element is added to select box we need to
7935 // force reflow of newly added node in order to workaround delay
7936 // of initialization properties
7937 try {
7938 option.selected = optionSet = true;
7939
7940 } catch ( _ ) {
7941
7942 // Will be executed only in IE6
7943 option.scrollHeight;
7944 }
7945
7946 } else {
7947 option.selected = false;
7948 }
7949 }
7950
7951 // Force browsers to behave consistently when non-matching value is set
7952 if ( !optionSet ) {
7953 elem.selectedIndex = -1;
7954 }
7955
7956 return options;
7957 }
7958 }
7959 }
7960});
7961
7962// Radios and checkboxes getter/setter
7963jQuery.each([ "radio", "checkbox" ], function() {
7964 jQuery.valHooks[ this ] = {
7965 set: function( elem, value ) {
7966 if ( jQuery.isArray( value ) ) {
7967 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
7968 }
7969 }
7970 };
7971 if ( !support.checkOn ) {
7972 jQuery.valHooks[ this ].get = function( elem ) {
7973 // Support: Webkit
7974 // "" is returned instead of "on" if a value isn't specified
7975 return elem.getAttribute("value") === null ? "on" : elem.value;
7976 };
7977 }
7978});
7979
7980
7981
7982
7983var nodeHook, boolHook,
7984 attrHandle = jQuery.expr.attrHandle,
7985 ruseDefault = /^(?:checked|selected)$/i,
7986 getSetAttribute = support.getSetAttribute,
7987 getSetInput = support.input;
7988
7989jQuery.fn.extend({
7990 attr: function( name, value ) {
7991 return access( this, jQuery.attr, name, value, arguments.length > 1 );
7992 },
7993
7994 removeAttr: function( name ) {
7995 return this.each(function() {
7996 jQuery.removeAttr( this, name );
7997 });
7998 }
7999});
8000
8001jQuery.extend({
8002 attr: function( elem, name, value ) {
8003 var hooks, ret,
8004 nType = elem.nodeType;
8005
8006 // don't get/set attributes on text, comment and attribute nodes
8007 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
8008 return;
8009 }
8010
8011 // Fallback to prop when attributes are not supported
8012 if ( typeof elem.getAttribute === strundefined ) {
8013 return jQuery.prop( elem, name, value );
8014 }
8015
8016 // All attributes are lowercase
8017 // Grab necessary hook if one is defined
8018 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
8019 name = name.toLowerCase();
8020 hooks = jQuery.attrHooks[ name ] ||
8021 ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
8022 }
8023
8024 if ( value !== undefined ) {
8025
8026 if ( value === null ) {
8027 jQuery.removeAttr( elem, name );
8028
8029 } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
8030 return ret;
8031
8032 } else {
8033 elem.setAttribute( name, value + "" );
8034 return value;
8035 }
8036
8037 } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
8038 return ret;
8039
8040 } else {
8041 ret = jQuery.find.attr( elem, name );
8042
8043 // Non-existent attributes return null, we normalize to undefined
8044 return ret == null ?
8045 undefined :
8046 ret;
8047 }
8048 },
8049
8050 removeAttr: function( elem, value ) {
8051 var name, propName,
8052 i = 0,
8053 attrNames = value && value.match( rnotwhite );
8054
8055 if ( attrNames && elem.nodeType === 1 ) {
8056 while ( (name = attrNames[i++]) ) {
8057 propName = jQuery.propFix[ name ] || name;
8058
8059 // Boolean attributes get special treatment (#10870)
8060 if ( jQuery.expr.match.bool.test( name ) ) {
8061 // Set corresponding property to false
8062 if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
8063 elem[ propName ] = false;
8064 // Support: IE<9
8065 // Also clear defaultChecked/defaultSelected (if appropriate)
8066 } else {
8067 elem[ jQuery.camelCase( "default-" + name ) ] =
8068 elem[ propName ] = false;
8069 }
8070
8071 // See #9699 for explanation of this approach (setting first, then removal)
8072 } else {
8073 jQuery.attr( elem, name, "" );
8074 }
8075
8076 elem.removeAttribute( getSetAttribute ? name : propName );
8077 }
8078 }
8079 },
8080
8081 attrHooks: {
8082 type: {
8083 set: function( elem, value ) {
8084 if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
8085 // Setting the type on a radio button after the value resets the value in IE6-9
8086 // Reset value to default in case type is set after value during creation
8087 var val = elem.value;
8088 elem.setAttribute( "type", value );
8089 if ( val ) {
8090 elem.value = val;
8091 }
8092 return value;
8093 }
8094 }
8095 }
8096 }
8097});
8098
8099// Hook for boolean attributes
8100boolHook = {
8101 set: function( elem, value, name ) {
8102 if ( value === false ) {
8103 // Remove boolean attributes when set to false
8104 jQuery.removeAttr( elem, name );
8105 } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
8106 // IE<8 needs the *property* name
8107 elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
8108
8109 // Use defaultChecked and defaultSelected for oldIE
8110 } else {
8111 elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
8112 }
8113
8114 return name;
8115 }
8116};
8117
8118// Retrieve booleans specially
8119jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
8120
8121 var getter = attrHandle[ name ] || jQuery.find.attr;
8122
8123 attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
8124 function( elem, name, isXML ) {
8125 var ret, handle;
8126 if ( !isXML ) {
8127 // Avoid an infinite loop by temporarily removing this function from the getter
8128 handle = attrHandle[ name ];
8129 attrHandle[ name ] = ret;
8130 ret = getter( elem, name, isXML ) != null ?
8131 name.toLowerCase() :
8132 null;
8133 attrHandle[ name ] = handle;
8134 }
8135 return ret;
8136 } :
8137 function( elem, name, isXML ) {
8138 if ( !isXML ) {
8139 return elem[ jQuery.camelCase( "default-" + name ) ] ?
8140 name.toLowerCase() :
8141 null;
8142 }
8143 };
8144});
8145
8146// fix oldIE attroperties
8147if ( !getSetInput || !getSetAttribute ) {
8148 jQuery.attrHooks.value = {
8149 set: function( elem, value, name ) {
8150 if ( jQuery.nodeName( elem, "input" ) ) {
8151 // Does not return so that setAttribute is also used
8152 elem.defaultValue = value;
8153 } else {
8154 // Use nodeHook if defined (#1954); otherwise setAttribute is fine
8155 return nodeHook && nodeHook.set( elem, value, name );
8156 }
8157 }
8158 };
8159}
8160
8161// IE6/7 do not support getting/setting some attributes with get/setAttribute
8162if ( !getSetAttribute ) {
8163
8164 // Use this for any attribute in IE6/7
8165 // This fixes almost every IE6/7 issue
8166 nodeHook = {
8167 set: function( elem, value, name ) {
8168 // Set the existing or create a new attribute node
8169 var ret = elem.getAttributeNode( name );
8170 if ( !ret ) {
8171 elem.setAttributeNode(
8172 (ret = elem.ownerDocument.createAttribute( name ))
8173 );
8174 }
8175
8176 ret.value = value += "";
8177
8178 // Break association with cloned elements by also using setAttribute (#9646)
8179 if ( name === "value" || value === elem.getAttribute( name ) ) {
8180 return value;
8181 }
8182 }
8183 };
8184
8185 // Some attributes are constructed with empty-string values when not defined
8186 attrHandle.id = attrHandle.name = attrHandle.coords =
8187 function( elem, name, isXML ) {
8188 var ret;
8189 if ( !isXML ) {
8190 return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
8191 ret.value :
8192 null;
8193 }
8194 };
8195
8196 // Fixing value retrieval on a button requires this module
8197 jQuery.valHooks.button = {
8198 get: function( elem, name ) {
8199 var ret = elem.getAttributeNode( name );
8200 if ( ret && ret.specified ) {
8201 return ret.value;
8202 }
8203 },
8204 set: nodeHook.set
8205 };
8206
8207 // Set contenteditable to false on removals(#10429)
8208 // Setting to empty string throws an error as an invalid value
8209 jQuery.attrHooks.contenteditable = {
8210 set: function( elem, value, name ) {
8211 nodeHook.set( elem, value === "" ? false : value, name );
8212 }
8213 };
8214
8215 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
8216 // This is for removals
8217 jQuery.each([ "width", "height" ], function( i, name ) {
8218 jQuery.attrHooks[ name ] = {
8219 set: function( elem, value ) {
8220 if ( value === "" ) {
8221 elem.setAttribute( name, "auto" );
8222 return value;
8223 }
8224 }
8225 };
8226 });
8227}
8228
8229if ( !support.style ) {
8230 jQuery.attrHooks.style = {
8231 get: function( elem ) {
8232 // Return undefined in the case of empty string
8233 // Note: IE uppercases css property names, but if we were to .toLowerCase()
8234 // .cssText, that would destroy case senstitivity in URL's, like in "background"
8235 return elem.style.cssText || undefined;
8236 },
8237 set: function( elem, value ) {
8238 return ( elem.style.cssText = value + "" );
8239 }
8240 };
8241}
8242
8243
8244
8245
8246var rfocusable = /^(?:input|select|textarea|button|object)$/i,
8247 rclickable = /^(?:a|area)$/i;
8248
8249jQuery.fn.extend({
8250 prop: function( name, value ) {
8251 return access( this, jQuery.prop, name, value, arguments.length > 1 );
8252 },
8253
8254 removeProp: function( name ) {
8255 name = jQuery.propFix[ name ] || name;
8256 return this.each(function() {
8257 // try/catch handles cases where IE balks (such as removing a property on window)
8258 try {
8259 this[ name ] = undefined;
8260 delete this[ name ];
8261 } catch( e ) {}
8262 });
8263 }
8264});
8265
8266jQuery.extend({
8267 propFix: {
8268 "for": "htmlFor",
8269 "class": "className"
8270 },
8271
8272 prop: function( elem, name, value ) {
8273 var ret, hooks, notxml,
8274 nType = elem.nodeType;
8275
8276 // don't get/set properties on text, comment and attribute nodes
8277 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
8278 return;
8279 }
8280
8281 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
8282
8283 if ( notxml ) {
8284 // Fix name and attach hooks
8285 name = jQuery.propFix[ name ] || name;
8286 hooks = jQuery.propHooks[ name ];
8287 }
8288
8289 if ( value !== undefined ) {
8290 return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
8291 ret :
8292 ( elem[ name ] = value );
8293
8294 } else {
8295 return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
8296 ret :
8297 elem[ name ];
8298 }
8299 },
8300
8301 propHooks: {
8302 tabIndex: {
8303 get: function( elem ) {
8304 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
8305 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
8306 // Use proper attribute retrieval(#12072)
8307 var tabindex = jQuery.find.attr( elem, "tabindex" );
8308
8309 return tabindex ?
8310 parseInt( tabindex, 10 ) :
8311 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
8312 0 :
8313 -1;
8314 }
8315 }
8316 }
8317});
8318
8319// Some attributes require a special call on IE
8320// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
8321if ( !support.hrefNormalized ) {
8322 // href/src property should get the full normalized URL (#10299/#12915)
8323 jQuery.each([ "href", "src" ], function( i, name ) {
8324 jQuery.propHooks[ name ] = {
8325 get: function( elem ) {
8326 return elem.getAttribute( name, 4 );
8327 }
8328 };
8329 });
8330}
8331
8332// Support: Safari, IE9+
8333// mis-reports the default selected property of an option
8334// Accessing the parent's selectedIndex property fixes it
8335if ( !support.optSelected ) {
8336 jQuery.propHooks.selected = {
8337 get: function( elem ) {
8338 var parent = elem.parentNode;
8339
8340 if ( parent ) {
8341 parent.selectedIndex;
8342
8343 // Make sure that it also works with optgroups, see #5701
8344 if ( parent.parentNode ) {
8345 parent.parentNode.selectedIndex;
8346 }
8347 }
8348 return null;
8349 }
8350 };
8351}
8352
8353jQuery.each([
8354 "tabIndex",
8355 "readOnly",
8356 "maxLength",
8357 "cellSpacing",
8358 "cellPadding",
8359 "rowSpan",
8360 "colSpan",
8361 "useMap",
8362 "frameBorder",
8363 "contentEditable"
8364], function() {
8365 jQuery.propFix[ this.toLowerCase() ] = this;
8366});
8367
8368// IE6/7 call enctype encoding
8369if ( !support.enctype ) {
8370 jQuery.propFix.enctype = "encoding";
8371}
8372
8373
8374
8375
8376var rclass = /[\t\r\n\f]/g;
8377
8378jQuery.fn.extend({
8379 addClass: function( value ) {
8380 var classes, elem, cur, clazz, j, finalValue,
8381 i = 0,
8382 len = this.length,
8383 proceed = typeof value === "string" && value;
8384
8385 if ( jQuery.isFunction( value ) ) {
8386 return this.each(function( j ) {
8387 jQuery( this ).addClass( value.call( this, j, this.className ) );
8388 });
8389 }
8390
8391 if ( proceed ) {
8392 // The disjunction here is for better compressibility (see removeClass)
8393 classes = ( value || "" ).match( rnotwhite ) || [];
8394
8395 for ( ; i < len; i++ ) {
8396 elem = this[ i ];
8397 cur = elem.nodeType === 1 && ( elem.className ?
8398 ( " " + elem.className + " " ).replace( rclass, " " ) :
8399 " "
8400 );
8401
8402 if ( cur ) {
8403 j = 0;
8404 while ( (clazz = classes[j++]) ) {
8405 if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
8406 cur += clazz + " ";
8407 }
8408 }
8409
8410 // only assign if different to avoid unneeded rendering.
8411 finalValue = jQuery.trim( cur );
8412 if ( elem.className !== finalValue ) {
8413 elem.className = finalValue;
8414 }
8415 }
8416 }
8417 }
8418
8419 return this;
8420 },
8421
8422 removeClass: function( value ) {
8423 var classes, elem, cur, clazz, j, finalValue,
8424 i = 0,
8425 len = this.length,
8426 proceed = arguments.length === 0 || typeof value === "string" && value;
8427
8428 if ( jQuery.isFunction( value ) ) {
8429 return this.each(function( j ) {
8430 jQuery( this ).removeClass( value.call( this, j, this.className ) );
8431 });
8432 }
8433 if ( proceed ) {
8434 classes = ( value || "" ).match( rnotwhite ) || [];
8435
8436 for ( ; i < len; i++ ) {
8437 elem = this[ i ];
8438 // This expression is here for better compressibility (see addClass)
8439 cur = elem.nodeType === 1 && ( elem.className ?
8440 ( " " + elem.className + " " ).replace( rclass, " " ) :
8441 ""
8442 );
8443
8444 if ( cur ) {
8445 j = 0;
8446 while ( (clazz = classes[j++]) ) {
8447 // Remove *all* instances
8448 while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
8449 cur = cur.replace( " " + clazz + " ", " " );
8450 }
8451 }
8452
8453 // only assign if different to avoid unneeded rendering.
8454 finalValue = value ? jQuery.trim( cur ) : "";
8455 if ( elem.className !== finalValue ) {
8456 elem.className = finalValue;
8457 }
8458 }
8459 }
8460 }
8461
8462 return this;
8463 },
8464
8465 toggleClass: function( value, stateVal ) {
8466 var type = typeof value;
8467
8468 if ( typeof stateVal === "boolean" && type === "string" ) {
8469 return stateVal ? this.addClass( value ) : this.removeClass( value );
8470 }
8471
8472 if ( jQuery.isFunction( value ) ) {
8473 return this.each(function( i ) {
8474 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
8475 });
8476 }
8477
8478 return this.each(function() {
8479 if ( type === "string" ) {
8480 // toggle individual class names
8481 var className,
8482 i = 0,
8483 self = jQuery( this ),
8484 classNames = value.match( rnotwhite ) || [];
8485
8486 while ( (className = classNames[ i++ ]) ) {
8487 // check each className given, space separated list
8488 if ( self.hasClass( className ) ) {
8489 self.removeClass( className );
8490 } else {
8491 self.addClass( className );
8492 }
8493 }
8494
8495 // Toggle whole class name
8496 } else if ( type === strundefined || type === "boolean" ) {
8497 if ( this.className ) {
8498 // store className if set
8499 jQuery._data( this, "__className__", this.className );
8500 }
8501
8502 // If the element has a class name or if we're passed "false",
8503 // then remove the whole classname (if there was one, the above saved it).
8504 // Otherwise bring back whatever was previously saved (if anything),
8505 // falling back to the empty string if nothing was stored.
8506 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
8507 }
8508 });
8509 },
8510
8511 hasClass: function( selector ) {
8512 var className = " " + selector + " ",
8513 i = 0,
8514 l = this.length;
8515 for ( ; i < l; i++ ) {
8516 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
8517 return true;
8518 }
8519 }
8520
8521 return false;
8522 }
8523});
8524
8525
8526
8527
8528// Return jQuery for attributes-only inclusion
8529
8530
8531jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
8532 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
8533 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
8534
8535 // Handle event binding
8536 jQuery.fn[ name ] = function( data, fn ) {
8537 return arguments.length > 0 ?
8538 this.on( name, null, data, fn ) :
8539 this.trigger( name );
8540 };
8541});
8542
8543jQuery.fn.extend({
8544 hover: function( fnOver, fnOut ) {
8545 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
8546 },
8547
8548 bind: function( types, data, fn ) {
8549 return this.on( types, null, data, fn );
8550 },
8551 unbind: function( types, fn ) {
8552 return this.off( types, null, fn );
8553 },
8554
8555 delegate: function( selector, types, data, fn ) {
8556 return this.on( types, selector, data, fn );
8557 },
8558 undelegate: function( selector, types, fn ) {
8559 // ( namespace ) or ( selector, types [, fn] )
8560 return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
8561 }
8562});
8563
8564
8565var nonce = jQuery.now();
8566
8567var rquery = (/\?/);
8568
8569
8570
8571var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
8572
8573jQuery.parseJSON = function( data ) {
8574 // Attempt to parse using the native JSON parser first
8575 if ( window.JSON && window.JSON.parse ) {
8576 // Support: Android 2.3
8577 // Workaround failure to string-cast null input
8578 return window.JSON.parse( data + "" );
8579 }
8580
8581 var requireNonComma,
8582 depth = null,
8583 str = jQuery.trim( data + "" );
8584
8585 // Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
8586 // after removing valid tokens
8587 return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
8588
8589 // Force termination if we see a misplaced comma
8590 if ( requireNonComma && comma ) {
8591 depth = 0;
8592 }
8593
8594 // Perform no more replacements after returning to outermost depth
8595 if ( depth === 0 ) {
8596 return token;
8597 }
8598
8599 // Commas must not follow "[", "{", or ","
8600 requireNonComma = open || comma;
8601
8602 // Determine new depth
8603 // array/object open ("[" or "{"): depth += true - false (increment)
8604 // array/object close ("]" or "}"): depth += false - true (decrement)
8605 // other cases ("," or primitive): depth += true - true (numeric cast)
8606 depth += !close - !open;
8607
8608 // Remove this token
8609 return "";
8610 }) ) ?
8611 ( Function( "return " + str ) )() :
8612 jQuery.error( "Invalid JSON: " + data );
8613};
8614
8615
8616// Cross-browser xml parsing
8617jQuery.parseXML = function( data ) {
8618 var xml, tmp;
8619 if ( !data || typeof data !== "string" ) {
8620 return null;
8621 }
8622 try {
8623 if ( window.DOMParser ) { // Standard
8624 tmp = new DOMParser();
8625 xml = tmp.parseFromString( data, "text/xml" );
8626 } else { // IE
8627 xml = new ActiveXObject( "Microsoft.XMLDOM" );
8628 xml.async = "false";
8629 xml.loadXML( data );
8630 }
8631 } catch( e ) {
8632 xml = undefined;
8633 }
8634 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
8635 jQuery.error( "Invalid XML: " + data );
8636 }
8637 return xml;
8638};
8639
8640
8641var
8642 // Document location
8643 ajaxLocParts,
8644 ajaxLocation,
8645
8646 rhash = /#.*$/,
8647 rts = /([?&])_=[^&]*/,
8648 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
8649 // #7653, #8125, #8152: local protocol detection
8650 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
8651 rnoContent = /^(?:GET|HEAD)$/,
8652 rprotocol = /^\/\//,
8653 rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
8654
8655 /* Prefilters
8656 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
8657 * 2) These are called:
8658 * - BEFORE asking for a transport
8659 * - AFTER param serialization (s.data is a string if s.processData is true)
8660 * 3) key is the dataType
8661 * 4) the catchall symbol "*" can be used
8662 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
8663 */
8664 prefilters = {},
8665
8666 /* Transports bindings
8667 * 1) key is the dataType
8668 * 2) the catchall symbol "*" can be used
8669 * 3) selection will start with transport dataType and THEN go to "*" if needed
8670 */
8671 transports = {},
8672
8673 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
8674 allTypes = "*/".concat("*");
8675
8676// #8138, IE may throw an exception when accessing
8677// a field from window.location if document.domain has been set
8678try {
8679 ajaxLocation = location.href;
8680} catch( e ) {
8681 // Use the href attribute of an A element
8682 // since IE will modify it given document.location
8683 ajaxLocation = document.createElement( "a" );
8684 ajaxLocation.href = "";
8685 ajaxLocation = ajaxLocation.href;
8686}
8687
8688// Segment location into parts
8689ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
8690
8691// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
8692function addToPrefiltersOrTransports( structure ) {
8693
8694 // dataTypeExpression is optional and defaults to "*"
8695 return function( dataTypeExpression, func ) {
8696
8697 if ( typeof dataTypeExpression !== "string" ) {
8698 func = dataTypeExpression;
8699 dataTypeExpression = "*";
8700 }
8701
8702 var dataType,
8703 i = 0,
8704 dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
8705
8706 if ( jQuery.isFunction( func ) ) {
8707 // For each dataType in the dataTypeExpression
8708 while ( (dataType = dataTypes[i++]) ) {
8709 // Prepend if requested
8710 if ( dataType.charAt( 0 ) === "+" ) {
8711 dataType = dataType.slice( 1 ) || "*";
8712 (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
8713
8714 // Otherwise append
8715 } else {
8716 (structure[ dataType ] = structure[ dataType ] || []).push( func );
8717 }
8718 }
8719 }
8720 };
8721}
8722
8723// Base inspection function for prefilters and transports
8724function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
8725
8726 var inspected = {},
8727 seekingTransport = ( structure === transports );
8728
8729 function inspect( dataType ) {
8730 var selected;
8731 inspected[ dataType ] = true;
8732 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
8733 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
8734 if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
8735 options.dataTypes.unshift( dataTypeOrTransport );
8736 inspect( dataTypeOrTransport );
8737 return false;
8738 } else if ( seekingTransport ) {
8739 return !( selected = dataTypeOrTransport );
8740 }
8741 });
8742 return selected;
8743 }
8744
8745 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
8746}
8747
8748// A special extend for ajax options
8749// that takes "flat" options (not to be deep extended)
8750// Fixes #9887
8751function ajaxExtend( target, src ) {
8752 var deep, key,
8753 flatOptions = jQuery.ajaxSettings.flatOptions || {};
8754
8755 for ( key in src ) {
8756 if ( src[ key ] !== undefined ) {
8757 ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
8758 }
8759 }
8760 if ( deep ) {
8761 jQuery.extend( true, target, deep );
8762 }
8763
8764 return target;
8765}
8766
8767/* Handles responses to an ajax request:
8768 * - finds the right dataType (mediates between content-type and expected dataType)
8769 * - returns the corresponding response
8770 */
8771function ajaxHandleResponses( s, jqXHR, responses ) {
8772 var firstDataType, ct, finalDataType, type,
8773 contents = s.contents,
8774 dataTypes = s.dataTypes;
8775
8776 // Remove auto dataType and get content-type in the process
8777 while ( dataTypes[ 0 ] === "*" ) {
8778 dataTypes.shift();
8779 if ( ct === undefined ) {
8780 ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
8781 }
8782 }
8783
8784 // Check if we're dealing with a known content-type
8785 if ( ct ) {
8786 for ( type in contents ) {
8787 if ( contents[ type ] && contents[ type ].test( ct ) ) {
8788 dataTypes.unshift( type );
8789 break;
8790 }
8791 }
8792 }
8793
8794 // Check to see if we have a response for the expected dataType
8795 if ( dataTypes[ 0 ] in responses ) {
8796 finalDataType = dataTypes[ 0 ];
8797 } else {
8798 // Try convertible dataTypes
8799 for ( type in responses ) {
8800 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8801 finalDataType = type;
8802 break;
8803 }
8804 if ( !firstDataType ) {
8805 firstDataType = type;
8806 }
8807 }
8808 // Or just use first one
8809 finalDataType = finalDataType || firstDataType;
8810 }
8811
8812 // If we found a dataType
8813 // We add the dataType to the list if needed
8814 // and return the corresponding response
8815 if ( finalDataType ) {
8816 if ( finalDataType !== dataTypes[ 0 ] ) {
8817 dataTypes.unshift( finalDataType );
8818 }
8819 return responses[ finalDataType ];
8820 }
8821}
8822
8823/* Chain conversions given the request and the original response
8824 * Also sets the responseXXX fields on the jqXHR instance
8825 */
8826function ajaxConvert( s, response, jqXHR, isSuccess ) {
8827 var conv2, current, conv, tmp, prev,
8828 converters = {},
8829 // Work with a copy of dataTypes in case we need to modify it for conversion
8830 dataTypes = s.dataTypes.slice();
8831
8832 // Create converters map with lowercased keys
8833 if ( dataTypes[ 1 ] ) {
8834 for ( conv in s.converters ) {
8835 converters[ conv.toLowerCase() ] = s.converters[ conv ];
8836 }
8837 }
8838
8839 current = dataTypes.shift();
8840
8841 // Convert to each sequential dataType
8842 while ( current ) {
8843
8844 if ( s.responseFields[ current ] ) {
8845 jqXHR[ s.responseFields[ current ] ] = response;
8846 }
8847
8848 // Apply the dataFilter if provided
8849 if ( !prev && isSuccess && s.dataFilter ) {
8850 response = s.dataFilter( response, s.dataType );
8851 }
8852
8853 prev = current;
8854 current = dataTypes.shift();
8855
8856 if ( current ) {
8857
8858 // There's only work to do if current dataType is non-auto
8859 if ( current === "*" ) {
8860
8861 current = prev;
8862
8863 // Convert response if prev dataType is non-auto and differs from current
8864 } else if ( prev !== "*" && prev !== current ) {
8865
8866 // Seek a direct converter
8867 conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8868
8869 // If none found, seek a pair
8870 if ( !conv ) {
8871 for ( conv2 in converters ) {
8872
8873 // If conv2 outputs current
8874 tmp = conv2.split( " " );
8875 if ( tmp[ 1 ] === current ) {
8876
8877 // If prev can be converted to accepted input
8878 conv = converters[ prev + " " + tmp[ 0 ] ] ||
8879 converters[ "* " + tmp[ 0 ] ];
8880 if ( conv ) {
8881 // Condense equivalence converters
8882 if ( conv === true ) {
8883 conv = converters[ conv2 ];
8884
8885 // Otherwise, insert the intermediate dataType
8886 } else if ( converters[ conv2 ] !== true ) {
8887 current = tmp[ 0 ];
8888 dataTypes.unshift( tmp[ 1 ] );
8889 }
8890 break;
8891 }
8892 }
8893 }
8894 }
8895
8896 // Apply converter (if not an equivalence)
8897 if ( conv !== true ) {
8898
8899 // Unless errors are allowed to bubble, catch and return them
8900 if ( conv && s[ "throws" ] ) {
8901 response = conv( response );
8902 } else {
8903 try {
8904 response = conv( response );
8905 } catch ( e ) {
8906 return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
8907 }
8908 }
8909 }
8910 }
8911 }
8912 }
8913
8914 return { state: "success", data: response };
8915}
8916
8917jQuery.extend({
8918
8919 // Counter for holding the number of active queries
8920 active: 0,
8921
8922 // Last-Modified header cache for next request
8923 lastModified: {},
8924 etag: {},
8925
8926 ajaxSettings: {
8927 url: ajaxLocation,
8928 type: "GET",
8929 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
8930 global: true,
8931 processData: true,
8932 async: true,
8933 contentType: "application/x-www-form-urlencoded; charset=UTF-8",
8934 /*
8935 timeout: 0,
8936 data: null,
8937 dataType: null,
8938 username: null,
8939 password: null,
8940 cache: null,
8941 throws: false,
8942 traditional: false,
8943 headers: {},
8944 */
8945
8946 accepts: {
8947 "*": allTypes,
8948 text: "text/plain",
8949 html: "text/html",
8950 xml: "application/xml, text/xml",
8951 json: "application/json, text/javascript"
8952 },
8953
8954 contents: {
8955 xml: /xml/,
8956 html: /html/,
8957 json: /json/
8958 },
8959
8960 responseFields: {
8961 xml: "responseXML",
8962 text: "responseText",
8963 json: "responseJSON"
8964 },
8965
8966 // Data converters
8967 // Keys separate source (or catchall "*") and destination types with a single space
8968 converters: {
8969
8970 // Convert anything to text
8971 "* text": String,
8972
8973 // Text to html (true = no transformation)
8974 "text html": true,
8975
8976 // Evaluate text as a json expression
8977 "text json": jQuery.parseJSON,
8978
8979 // Parse text as xml
8980 "text xml": jQuery.parseXML
8981 },
8982
8983 // For options that shouldn't be deep extended:
8984 // you can add your own custom options here if
8985 // and when you create one that shouldn't be
8986 // deep extended (see ajaxExtend)
8987 flatOptions: {
8988 url: true,
8989 context: true
8990 }
8991 },
8992
8993 // Creates a full fledged settings object into target
8994 // with both ajaxSettings and settings fields.
8995 // If target is omitted, writes into ajaxSettings.
8996 ajaxSetup: function( target, settings ) {
8997 return settings ?
8998
8999 // Building a settings object
9000 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
9001
9002 // Extending ajaxSettings
9003 ajaxExtend( jQuery.ajaxSettings, target );
9004 },
9005
9006 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
9007 ajaxTransport: addToPrefiltersOrTransports( transports ),
9008
9009 // Main method
9010 ajax: function( url, options ) {
9011
9012 // If url is an object, simulate pre-1.5 signature
9013 if ( typeof url === "object" ) {
9014 options = url;
9015 url = undefined;
9016 }
9017
9018 // Force options to be an object
9019 options = options || {};
9020
9021 var // Cross-domain detection vars
9022 parts,
9023 // Loop variable
9024 i,
9025 // URL without anti-cache param
9026 cacheURL,
9027 // Response headers as string
9028 responseHeadersString,
9029 // timeout handle
9030 timeoutTimer,
9031
9032 // To know if global events are to be dispatched
9033 fireGlobals,
9034
9035 transport,
9036 // Response headers
9037 responseHeaders,
9038 // Create the final options object
9039 s = jQuery.ajaxSetup( {}, options ),
9040 // Callbacks context
9041 callbackContext = s.context || s,
9042 // Context for global events is callbackContext if it is a DOM node or jQuery collection
9043 globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
9044 jQuery( callbackContext ) :
9045 jQuery.event,
9046 // Deferreds
9047 deferred = jQuery.Deferred(),
9048 completeDeferred = jQuery.Callbacks("once memory"),
9049 // Status-dependent callbacks
9050 statusCode = s.statusCode || {},
9051 // Headers (they are sent all at once)
9052 requestHeaders = {},
9053 requestHeadersNames = {},
9054 // The jqXHR state
9055 state = 0,
9056 // Default abort message
9057 strAbort = "canceled",
9058 // Fake xhr
9059 jqXHR = {
9060 readyState: 0,
9061
9062 // Builds headers hashtable if needed
9063 getResponseHeader: function( key ) {
9064 var match;
9065 if ( state === 2 ) {
9066 if ( !responseHeaders ) {
9067 responseHeaders = {};
9068 while ( (match = rheaders.exec( responseHeadersString )) ) {
9069 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
9070 }
9071 }
9072 match = responseHeaders[ key.toLowerCase() ];
9073 }
9074 return match == null ? null : match;
9075 },
9076
9077 // Raw string
9078 getAllResponseHeaders: function() {
9079 return state === 2 ? responseHeadersString : null;
9080 },
9081
9082 // Caches the header
9083 setRequestHeader: function( name, value ) {
9084 var lname = name.toLowerCase();
9085 if ( !state ) {
9086 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
9087 requestHeaders[ name ] = value;
9088 }
9089 return this;
9090 },
9091
9092 // Overrides response content-type header
9093 overrideMimeType: function( type ) {
9094 if ( !state ) {
9095 s.mimeType = type;
9096 }
9097 return this;
9098 },
9099
9100 // Status-dependent callbacks
9101 statusCode: function( map ) {
9102 var code;
9103 if ( map ) {
9104 if ( state < 2 ) {
9105 for ( code in map ) {
9106 // Lazy-add the new callback in a way that preserves old ones
9107 statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
9108 }
9109 } else {
9110 // Execute the appropriate callbacks
9111 jqXHR.always( map[ jqXHR.status ] );
9112 }
9113 }
9114 return this;
9115 },
9116
9117 // Cancel the request
9118 abort: function( statusText ) {
9119 var finalText = statusText || strAbort;
9120 if ( transport ) {
9121 transport.abort( finalText );
9122 }
9123 done( 0, finalText );
9124 return this;
9125 }
9126 };
9127
9128 // Attach deferreds
9129 deferred.promise( jqXHR ).complete = completeDeferred.add;
9130 jqXHR.success = jqXHR.done;
9131 jqXHR.error = jqXHR.fail;
9132
9133 // Remove hash character (#7531: and string promotion)
9134 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
9135 // Handle falsy url in the settings object (#10093: consistency with old signature)
9136 // We also use the url parameter if available
9137 s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
9138
9139 // Alias method option to type as per ticket #12004
9140 s.type = options.method || options.type || s.method || s.type;
9141
9142 // Extract dataTypes list
9143 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
9144
9145 // A cross-domain request is in order when we have a protocol:host:port mismatch
9146 if ( s.crossDomain == null ) {
9147 parts = rurl.exec( s.url.toLowerCase() );
9148 s.crossDomain = !!( parts &&
9149 ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
9150 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
9151 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
9152 );
9153 }
9154
9155 // Convert data if not already a string
9156 if ( s.data && s.processData && typeof s.data !== "string" ) {
9157 s.data = jQuery.param( s.data, s.traditional );
9158 }
9159
9160 // Apply prefilters
9161 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
9162
9163 // If request was aborted inside a prefilter, stop there
9164 if ( state === 2 ) {
9165 return jqXHR;
9166 }
9167
9168 // We can fire global events as of now if asked to
9169 fireGlobals = s.global;
9170
9171 // Watch for a new set of requests
9172 if ( fireGlobals && jQuery.active++ === 0 ) {
9173 jQuery.event.trigger("ajaxStart");
9174 }
9175
9176 // Uppercase the type
9177 s.type = s.type.toUpperCase();
9178
9179 // Determine if request has content
9180 s.hasContent = !rnoContent.test( s.type );
9181
9182 // Save the URL in case we're toying with the If-Modified-Since
9183 // and/or If-None-Match header later on
9184 cacheURL = s.url;
9185
9186 // More options handling for requests with no content
9187 if ( !s.hasContent ) {
9188
9189 // If data is available, append data to url
9190 if ( s.data ) {
9191 cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
9192 // #9682: remove data so that it's not used in an eventual retry
9193 delete s.data;
9194 }
9195
9196 // Add anti-cache in url if needed
9197 if ( s.cache === false ) {
9198 s.url = rts.test( cacheURL ) ?
9199
9200 // If there is already a '_' parameter, set its value
9201 cacheURL.replace( rts, "$1_=" + nonce++ ) :
9202
9203 // Otherwise add one to the end
9204 cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
9205 }
9206 }
9207
9208 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9209 if ( s.ifModified ) {
9210 if ( jQuery.lastModified[ cacheURL ] ) {
9211 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
9212 }
9213 if ( jQuery.etag[ cacheURL ] ) {
9214 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
9215 }
9216 }
9217
9218 // Set the correct header, if data is being sent
9219 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
9220 jqXHR.setRequestHeader( "Content-Type", s.contentType );
9221 }
9222
9223 // Set the Accepts header for the server, depending on the dataType
9224 jqXHR.setRequestHeader(
9225 "Accept",
9226 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
9227 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
9228 s.accepts[ "*" ]
9229 );
9230
9231 // Check for headers option
9232 for ( i in s.headers ) {
9233 jqXHR.setRequestHeader( i, s.headers[ i ] );
9234 }
9235
9236 // Allow custom headers/mimetypes and early abort
9237 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
9238 // Abort if not done already and return
9239 return jqXHR.abort();
9240 }
9241
9242 // aborting is no longer a cancellation
9243 strAbort = "abort";
9244
9245 // Install callbacks on deferreds
9246 for ( i in { success: 1, error: 1, complete: 1 } ) {
9247 jqXHR[ i ]( s[ i ] );
9248 }
9249
9250 // Get transport
9251 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
9252
9253 // If no transport, we auto-abort
9254 if ( !transport ) {
9255 done( -1, "No Transport" );
9256 } else {
9257 jqXHR.readyState = 1;
9258
9259 // Send global event
9260 if ( fireGlobals ) {
9261 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
9262 }
9263 // Timeout
9264 if ( s.async && s.timeout > 0 ) {
9265 timeoutTimer = setTimeout(function() {
9266 jqXHR.abort("timeout");
9267 }, s.timeout );
9268 }
9269
9270 try {
9271 state = 1;
9272 transport.send( requestHeaders, done );
9273 } catch ( e ) {
9274 // Propagate exception as error if not done
9275 if ( state < 2 ) {
9276 done( -1, e );
9277 // Simply rethrow otherwise
9278 } else {
9279 throw e;
9280 }
9281 }
9282 }
9283
9284 // Callback for when everything is done
9285 function done( status, nativeStatusText, responses, headers ) {
9286 var isSuccess, success, error, response, modified,
9287 statusText = nativeStatusText;
9288
9289 // Called once
9290 if ( state === 2 ) {
9291 return;
9292 }
9293
9294 // State is "done" now
9295 state = 2;
9296
9297 // Clear timeout if it exists
9298 if ( timeoutTimer ) {
9299 clearTimeout( timeoutTimer );
9300 }
9301
9302 // Dereference transport for early garbage collection
9303 // (no matter how long the jqXHR object will be used)
9304 transport = undefined;
9305
9306 // Cache response headers
9307 responseHeadersString = headers || "";
9308
9309 // Set readyState
9310 jqXHR.readyState = status > 0 ? 4 : 0;
9311
9312 // Determine if successful
9313 isSuccess = status >= 200 && status < 300 || status === 304;
9314
9315 // Get response data
9316 if ( responses ) {
9317 response = ajaxHandleResponses( s, jqXHR, responses );
9318 }
9319
9320 // Convert no matter what (that way responseXXX fields are always set)
9321 response = ajaxConvert( s, response, jqXHR, isSuccess );
9322
9323 // If successful, handle type chaining
9324 if ( isSuccess ) {
9325
9326 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9327 if ( s.ifModified ) {
9328 modified = jqXHR.getResponseHeader("Last-Modified");
9329 if ( modified ) {
9330 jQuery.lastModified[ cacheURL ] = modified;
9331 }
9332 modified = jqXHR.getResponseHeader("etag");
9333 if ( modified ) {
9334 jQuery.etag[ cacheURL ] = modified;
9335 }
9336 }
9337
9338 // if no content
9339 if ( status === 204 || s.type === "HEAD" ) {
9340 statusText = "nocontent";
9341
9342 // if not modified
9343 } else if ( status === 304 ) {
9344 statusText = "notmodified";
9345
9346 // If we have data, let's convert it
9347 } else {
9348 statusText = response.state;
9349 success = response.data;
9350 error = response.error;
9351 isSuccess = !error;
9352 }
9353 } else {
9354 // We extract error from statusText
9355 // then normalize statusText and status for non-aborts
9356 error = statusText;
9357 if ( status || !statusText ) {
9358 statusText = "error";
9359 if ( status < 0 ) {
9360 status = 0;
9361 }
9362 }
9363 }
9364
9365 // Set data for the fake xhr object
9366 jqXHR.status = status;
9367 jqXHR.statusText = ( nativeStatusText || statusText ) + "";
9368
9369 // Success/Error
9370 if ( isSuccess ) {
9371 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
9372 } else {
9373 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
9374 }
9375
9376 // Status-dependent callbacks
9377 jqXHR.statusCode( statusCode );
9378 statusCode = undefined;
9379
9380 if ( fireGlobals ) {
9381 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
9382 [ jqXHR, s, isSuccess ? success : error ] );
9383 }
9384
9385 // Complete
9386 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
9387
9388 if ( fireGlobals ) {
9389 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
9390 // Handle the global AJAX counter
9391 if ( !( --jQuery.active ) ) {
9392 jQuery.event.trigger("ajaxStop");
9393 }
9394 }
9395 }
9396
9397 return jqXHR;
9398 },
9399
9400 getJSON: function( url, data, callback ) {
9401 return jQuery.get( url, data, callback, "json" );
9402 },
9403
9404 getScript: function( url, callback ) {
9405 return jQuery.get( url, undefined, callback, "script" );
9406 }
9407});
9408
9409jQuery.each( [ "get", "post" ], function( i, method ) {
9410 jQuery[ method ] = function( url, data, callback, type ) {
9411 // shift arguments if data argument was omitted
9412 if ( jQuery.isFunction( data ) ) {
9413 type = type || callback;
9414 callback = data;
9415 data = undefined;
9416 }
9417
9418 return jQuery.ajax({
9419 url: url,
9420 type: method,
9421 dataType: type,
9422 data: data,
9423 success: callback
9424 });
9425 };
9426});
9427
9428// Attach a bunch of functions for handling common AJAX events
9429jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
9430 jQuery.fn[ type ] = function( fn ) {
9431 return this.on( type, fn );
9432 };
9433});
9434
9435
9436jQuery._evalUrl = function( url ) {
9437 return jQuery.ajax({
9438 url: url,
9439 type: "GET",
9440 dataType: "script",
9441 async: false,
9442 global: false,
9443 "throws": true
9444 });
9445};
9446
9447
9448jQuery.fn.extend({
9449 wrapAll: function( html ) {
9450 if ( jQuery.isFunction( html ) ) {
9451 return this.each(function(i) {
9452 jQuery(this).wrapAll( html.call(this, i) );
9453 });
9454 }
9455
9456 if ( this[0] ) {
9457 // The elements to wrap the target around
9458 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
9459
9460 if ( this[0].parentNode ) {
9461 wrap.insertBefore( this[0] );
9462 }
9463
9464 wrap.map(function() {
9465 var elem = this;
9466
9467 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
9468 elem = elem.firstChild;
9469 }
9470
9471 return elem;
9472 }).append( this );
9473 }
9474
9475 return this;
9476 },
9477
9478 wrapInner: function( html ) {
9479 if ( jQuery.isFunction( html ) ) {
9480 return this.each(function(i) {
9481 jQuery(this).wrapInner( html.call(this, i) );
9482 });
9483 }
9484
9485 return this.each(function() {
9486 var self = jQuery( this ),
9487 contents = self.contents();
9488
9489 if ( contents.length ) {
9490 contents.wrapAll( html );
9491
9492 } else {
9493 self.append( html );
9494 }
9495 });
9496 },
9497
9498 wrap: function( html ) {
9499 var isFunction = jQuery.isFunction( html );
9500
9501 return this.each(function(i) {
9502 jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
9503 });
9504 },
9505
9506 unwrap: function() {
9507 return this.parent().each(function() {
9508 if ( !jQuery.nodeName( this, "body" ) ) {
9509 jQuery( this ).replaceWith( this.childNodes );
9510 }
9511 }).end();
9512 }
9513});
9514
9515
9516jQuery.expr.filters.hidden = function( elem ) {
9517 // Support: Opera <= 12.12
9518 // Opera reports offsetWidths and offsetHeights less than zero on some elements
9519 return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
9520 (!support.reliableHiddenOffsets() &&
9521 ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
9522};
9523
9524jQuery.expr.filters.visible = function( elem ) {
9525 return !jQuery.expr.filters.hidden( elem );
9526};
9527
9528
9529
9530
9531var r20 = /%20/g,
9532 rbracket = /\[\]$/,
9533 rCRLF = /\r?\n/g,
9534 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
9535 rsubmittable = /^(?:input|select|textarea|keygen)/i;
9536
9537function buildParams( prefix, obj, traditional, add ) {
9538 var name;
9539
9540 if ( jQuery.isArray( obj ) ) {
9541 // Serialize array item.
9542 jQuery.each( obj, function( i, v ) {
9543 if ( traditional || rbracket.test( prefix ) ) {
9544 // Treat each array item as a scalar.
9545 add( prefix, v );
9546
9547 } else {
9548 // Item is non-scalar (array or object), encode its numeric index.
9549 buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
9550 }
9551 });
9552
9553 } else if ( !traditional && jQuery.type( obj ) === "object" ) {
9554 // Serialize object item.
9555 for ( name in obj ) {
9556 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
9557 }
9558
9559 } else {
9560 // Serialize scalar item.
9561 add( prefix, obj );
9562 }
9563}
9564
9565// Serialize an array of form elements or a set of
9566// key/values into a query string
9567jQuery.param = function( a, traditional ) {
9568 var prefix,
9569 s = [],
9570 add = function( key, value ) {
9571 // If value is a function, invoke it and return its value
9572 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
9573 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
9574 };
9575
9576 // Set traditional to true for jQuery <= 1.3.2 behavior.
9577 if ( traditional === undefined ) {
9578 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
9579 }
9580
9581 // If an array was passed in, assume that it is an array of form elements.
9582 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
9583 // Serialize the form elements
9584 jQuery.each( a, function() {
9585 add( this.name, this.value );
9586 });
9587
9588 } else {
9589 // If traditional, encode the "old" way (the way 1.3.2 or older
9590 // did it), otherwise encode params recursively.
9591 for ( prefix in a ) {
9592 buildParams( prefix, a[ prefix ], traditional, add );
9593 }
9594 }
9595
9596 // Return the resulting serialization
9597 return s.join( "&" ).replace( r20, "+" );
9598};
9599
9600jQuery.fn.extend({
9601 serialize: function() {
9602 return jQuery.param( this.serializeArray() );
9603 },
9604 serializeArray: function() {
9605 return this.map(function() {
9606 // Can add propHook for "elements" to filter or add form elements
9607 var elements = jQuery.prop( this, "elements" );
9608 return elements ? jQuery.makeArray( elements ) : this;
9609 })
9610 .filter(function() {
9611 var type = this.type;
9612 // Use .is(":disabled") so that fieldset[disabled] works
9613 return this.name && !jQuery( this ).is( ":disabled" ) &&
9614 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
9615 ( this.checked || !rcheckableType.test( type ) );
9616 })
9617 .map(function( i, elem ) {
9618 var val = jQuery( this ).val();
9619
9620 return val == null ?
9621 null :
9622 jQuery.isArray( val ) ?
9623 jQuery.map( val, function( val ) {
9624 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
9625 }) :
9626 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
9627 }).get();
9628 }
9629});
9630
9631
9632// Create the request object
9633// (This is still attached to ajaxSettings for backward compatibility)
9634jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
9635 // Support: IE6+
9636 function() {
9637
9638 // XHR cannot access local files, always use ActiveX for that case
9639 return !this.isLocal &&
9640
9641 // Support: IE7-8
9642 // oldIE XHR does not support non-RFC2616 methods (#13240)
9643 // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
9644 // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
9645 // Although this check for six methods instead of eight
9646 // since IE also does not support "trace" and "connect"
9647 /^(get|post|head|put|delete|options)$/i.test( this.type ) &&
9648
9649 createStandardXHR() || createActiveXHR();
9650 } :
9651 // For all other browsers, use the standard XMLHttpRequest object
9652 createStandardXHR;
9653
9654var xhrId = 0,
9655 xhrCallbacks = {},
9656 xhrSupported = jQuery.ajaxSettings.xhr();
9657
9658// Support: IE<10
9659// Open requests must be manually aborted on unload (#5280)
9660if ( window.ActiveXObject ) {
9661 jQuery( window ).on( "unload", function() {
9662 for ( var key in xhrCallbacks ) {
9663 xhrCallbacks[ key ]( undefined, true );
9664 }
9665 });
9666}
9667
9668// Determine support properties
9669support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
9670xhrSupported = support.ajax = !!xhrSupported;
9671
9672// Create transport if the browser can provide an xhr
9673if ( xhrSupported ) {
9674
9675 jQuery.ajaxTransport(function( options ) {
9676 // Cross domain only allowed if supported through XMLHttpRequest
9677 if ( !options.crossDomain || support.cors ) {
9678
9679 var callback;
9680
9681 return {
9682 send: function( headers, complete ) {
9683 var i,
9684 xhr = options.xhr(),
9685 id = ++xhrId;
9686
9687 // Open the socket
9688 xhr.open( options.type, options.url, options.async, options.username, options.password );
9689
9690 // Apply custom fields if provided
9691 if ( options.xhrFields ) {
9692 for ( i in options.xhrFields ) {
9693 xhr[ i ] = options.xhrFields[ i ];
9694 }
9695 }
9696
9697 // Override mime type if needed
9698 if ( options.mimeType && xhr.overrideMimeType ) {
9699 xhr.overrideMimeType( options.mimeType );
9700 }
9701
9702 // X-Requested-With header
9703 // For cross-domain requests, seeing as conditions for a preflight are
9704 // akin to a jigsaw puzzle, we simply never set it to be sure.
9705 // (it can always be set on a per-request basis or even using ajaxSetup)
9706 // For same-domain requests, won't change header if already provided.
9707 if ( !options.crossDomain && !headers["X-Requested-With"] ) {
9708 headers["X-Requested-With"] = "XMLHttpRequest";
9709 }
9710
9711 // Set headers
9712 for ( i in headers ) {
9713 // Support: IE<9
9714 // IE's ActiveXObject throws a 'Type Mismatch' exception when setting
9715 // request header to a null-value.
9716 //
9717 // To keep consistent with other XHR implementations, cast the value
9718 // to string and ignore `undefined`.
9719 if ( headers[ i ] !== undefined ) {
9720 xhr.setRequestHeader( i, headers[ i ] + "" );
9721 }
9722 }
9723
9724 // Do send the request
9725 // This may raise an exception which is actually
9726 // handled in jQuery.ajax (so no try/catch here)
9727 xhr.send( ( options.hasContent && options.data ) || null );
9728
9729 // Listener
9730 callback = function( _, isAbort ) {
9731 var status, statusText, responses;
9732
9733 // Was never called and is aborted or complete
9734 if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
9735 // Clean up
9736 delete xhrCallbacks[ id ];
9737 callback = undefined;
9738 xhr.onreadystatechange = jQuery.noop;
9739
9740 // Abort manually if needed
9741 if ( isAbort ) {
9742 if ( xhr.readyState !== 4 ) {
9743 xhr.abort();
9744 }
9745 } else {
9746 responses = {};
9747 status = xhr.status;
9748
9749 // Support: IE<10
9750 // Accessing binary-data responseText throws an exception
9751 // (#11426)
9752 if ( typeof xhr.responseText === "string" ) {
9753 responses.text = xhr.responseText;
9754 }
9755
9756 // Firefox throws an exception when accessing
9757 // statusText for faulty cross-domain requests
9758 try {
9759 statusText = xhr.statusText;
9760 } catch( e ) {
9761 // We normalize with Webkit giving an empty statusText
9762 statusText = "";
9763 }
9764
9765 // Filter status for non standard behaviors
9766
9767 // If the request is local and we have data: assume a success
9768 // (success with no data won't get notified, that's the best we
9769 // can do given current implementations)
9770 if ( !status && options.isLocal && !options.crossDomain ) {
9771 status = responses.text ? 200 : 404;
9772 // IE - #1450: sometimes returns 1223 when it should be 204
9773 } else if ( status === 1223 ) {
9774 status = 204;
9775 }
9776 }
9777 }
9778
9779 // Call complete if needed
9780 if ( responses ) {
9781 complete( status, statusText, responses, xhr.getAllResponseHeaders() );
9782 }
9783 };
9784
9785 if ( !options.async ) {
9786 // if we're in sync mode we fire the callback
9787 callback();
9788 } else if ( xhr.readyState === 4 ) {
9789 // (IE6 & IE7) if it's in cache and has been
9790 // retrieved directly we need to fire the callback
9791 setTimeout( callback );
9792 } else {
9793 // Add to the list of active xhr callbacks
9794 xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
9795 }
9796 },
9797
9798 abort: function() {
9799 if ( callback ) {
9800 callback( undefined, true );
9801 }
9802 }
9803 };
9804 }
9805 });
9806}
9807
9808// Functions to create xhrs
9809function createStandardXHR() {
9810 try {
9811 return new window.XMLHttpRequest();
9812 } catch( e ) {}
9813}
9814
9815function createActiveXHR() {
9816 try {
9817 return new window.ActiveXObject( "Microsoft.XMLHTTP" );
9818 } catch( e ) {}
9819}
9820
9821
9822
9823
9824// Install script dataType
9825jQuery.ajaxSetup({
9826 accepts: {
9827 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
9828 },
9829 contents: {
9830 script: /(?:java|ecma)script/
9831 },
9832 converters: {
9833 "text script": function( text ) {
9834 jQuery.globalEval( text );
9835 return text;
9836 }
9837 }
9838});
9839
9840// Handle cache's special case and global
9841jQuery.ajaxPrefilter( "script", function( s ) {
9842 if ( s.cache === undefined ) {
9843 s.cache = false;
9844 }
9845 if ( s.crossDomain ) {
9846 s.type = "GET";
9847 s.global = false;
9848 }
9849});
9850
9851// Bind script tag hack transport
9852jQuery.ajaxTransport( "script", function(s) {
9853
9854 // This transport only deals with cross domain requests
9855 if ( s.crossDomain ) {
9856
9857 var script,
9858 head = document.head || jQuery("head")[0] || document.documentElement;
9859
9860 return {
9861
9862 send: function( _, callback ) {
9863
9864 script = document.createElement("script");
9865
9866 script.async = true;
9867
9868 if ( s.scriptCharset ) {
9869 script.charset = s.scriptCharset;
9870 }
9871
9872 script.src = s.url;
9873
9874 // Attach handlers for all browsers
9875 script.onload = script.onreadystatechange = function( _, isAbort ) {
9876
9877 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
9878
9879 // Handle memory leak in IE
9880 script.onload = script.onreadystatechange = null;
9881
9882 // Remove the script
9883 if ( script.parentNode ) {
9884 script.parentNode.removeChild( script );
9885 }
9886
9887 // Dereference the script
9888 script = null;
9889
9890 // Callback if not abort
9891 if ( !isAbort ) {
9892 callback( 200, "success" );
9893 }
9894 }
9895 };
9896
9897 // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
9898 // Use native DOM manipulation to avoid our domManip AJAX trickery
9899 head.insertBefore( script, head.firstChild );
9900 },
9901
9902 abort: function() {
9903 if ( script ) {
9904 script.onload( undefined, true );
9905 }
9906 }
9907 };
9908 }
9909});
9910
9911
9912
9913
9914var oldCallbacks = [],
9915 rjsonp = /(=)\?(?=&|$)|\?\?/;
9916
9917// Default jsonp settings
9918jQuery.ajaxSetup({
9919 jsonp: "callback",
9920 jsonpCallback: function() {
9921 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
9922 this[ callback ] = true;
9923 return callback;
9924 }
9925});
9926
9927// Detect, normalize options and install callbacks for jsonp requests
9928jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
9929
9930 var callbackName, overwritten, responseContainer,
9931 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
9932 "url" :
9933 typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
9934 );
9935
9936 // Handle iff the expected data type is "jsonp" or we have a parameter to set
9937 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
9938
9939 // Get callback name, remembering preexisting value associated with it
9940 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
9941 s.jsonpCallback() :
9942 s.jsonpCallback;
9943
9944 // Insert callback into url or form data
9945 if ( jsonProp ) {
9946 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
9947 } else if ( s.jsonp !== false ) {
9948 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
9949 }
9950
9951 // Use data converter to retrieve json after script execution
9952 s.converters["script json"] = function() {
9953 if ( !responseContainer ) {
9954 jQuery.error( callbackName + " was not called" );
9955 }
9956 return responseContainer[ 0 ];
9957 };
9958
9959 // force json dataType
9960 s.dataTypes[ 0 ] = "json";
9961
9962 // Install callback
9963 overwritten = window[ callbackName ];
9964 window[ callbackName ] = function() {
9965 responseContainer = arguments;
9966 };
9967
9968 // Clean-up function (fires after converters)
9969 jqXHR.always(function() {
9970 // Restore preexisting value
9971 window[ callbackName ] = overwritten;
9972
9973 // Save back as free
9974 if ( s[ callbackName ] ) {
9975 // make sure that re-using the options doesn't screw things around
9976 s.jsonpCallback = originalSettings.jsonpCallback;
9977
9978 // save the callback name for future use
9979 oldCallbacks.push( callbackName );
9980 }
9981
9982 // Call if it was a function and we have a response
9983 if ( responseContainer && jQuery.isFunction( overwritten ) ) {
9984 overwritten( responseContainer[ 0 ] );
9985 }
9986
9987 responseContainer = overwritten = undefined;
9988 });
9989
9990 // Delegate to script
9991 return "script";
9992 }
9993});
9994
9995
9996
9997
9998// data: string of html
9999// context (optional): If specified, the fragment will be created in this context, defaults to document
10000// keepScripts (optional): If true, will include scripts passed in the html string
10001jQuery.parseHTML = function( data, context, keepScripts ) {
10002 if ( !data || typeof data !== "string" ) {
10003 return null;
10004 }
10005 if ( typeof context === "boolean" ) {
10006 keepScripts = context;
10007 context = false;
10008 }
10009 context = context || document;
10010
10011 var parsed = rsingleTag.exec( data ),
10012 scripts = !keepScripts && [];
10013
10014 // Single tag
10015 if ( parsed ) {
10016 return [ context.createElement( parsed[1] ) ];
10017 }
10018
10019 parsed = jQuery.buildFragment( [ data ], context, scripts );
10020
10021 if ( scripts && scripts.length ) {
10022 jQuery( scripts ).remove();
10023 }
10024
10025 return jQuery.merge( [], parsed.childNodes );
10026};
10027
10028
10029// Keep a copy of the old load method
10030var _load = jQuery.fn.load;
10031
10032/**
10033 * Load a url into a page
10034 */
10035jQuery.fn.load = function( url, params, callback ) {
10036 if ( typeof url !== "string" && _load ) {
10037 return _load.apply( this, arguments );
10038 }
10039
10040 var selector, response, type,
10041 self = this,
10042 off = url.indexOf(" ");
10043
10044 if ( off >= 0 ) {
10045 selector = jQuery.trim( url.slice( off, url.length ) );
10046 url = url.slice( 0, off );
10047 }
10048
10049 // If it's a function
10050 if ( jQuery.isFunction( params ) ) {
10051
10052 // We assume that it's the callback
10053 callback = params;
10054 params = undefined;
10055
10056 // Otherwise, build a param string
10057 } else if ( params && typeof params === "object" ) {
10058 type = "POST";
10059 }
10060
10061 // If we have elements to modify, make the request
10062 if ( self.length > 0 ) {
10063 jQuery.ajax({
10064 url: url,
10065
10066 // if "type" variable is undefined, then "GET" method will be used
10067 type: type,
10068 dataType: "html",
10069 data: params
10070 }).done(function( responseText ) {
10071
10072 // Save response for use in complete callback
10073 response = arguments;
10074
10075 self.html( selector ?
10076
10077 // If a selector was specified, locate the right elements in a dummy div
10078 // Exclude scripts to avoid IE 'Permission Denied' errors
10079 jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
10080
10081 // Otherwise use the full result
10082 responseText );
10083
10084 }).complete( callback && function( jqXHR, status ) {
10085 self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
10086 });
10087 }
10088
10089 return this;
10090};
10091
10092
10093
10094
10095jQuery.expr.filters.animated = function( elem ) {
10096 return jQuery.grep(jQuery.timers, function( fn ) {
10097 return elem === fn.elem;
10098 }).length;
10099};
10100
10101
10102
10103
10104
10105var docElem = window.document.documentElement;
10106
10107/**
10108 * Gets a window from an element
10109 */
10110function getWindow( elem ) {
10111 return jQuery.isWindow( elem ) ?
10112 elem :
10113 elem.nodeType === 9 ?
10114 elem.defaultView || elem.parentWindow :
10115 false;
10116}
10117
10118jQuery.offset = {
10119 setOffset: function( elem, options, i ) {
10120 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
10121 position = jQuery.css( elem, "position" ),
10122 curElem = jQuery( elem ),
10123 props = {};
10124
10125 // set position first, in-case top/left are set even on static elem
10126 if ( position === "static" ) {
10127 elem.style.position = "relative";
10128 }
10129
10130 curOffset = curElem.offset();
10131 curCSSTop = jQuery.css( elem, "top" );
10132 curCSSLeft = jQuery.css( elem, "left" );
10133 calculatePosition = ( position === "absolute" || position === "fixed" ) &&
10134 jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
10135
10136 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
10137 if ( calculatePosition ) {
10138 curPosition = curElem.position();
10139 curTop = curPosition.top;
10140 curLeft = curPosition.left;
10141 } else {
10142 curTop = parseFloat( curCSSTop ) || 0;
10143 curLeft = parseFloat( curCSSLeft ) || 0;
10144 }
10145
10146 if ( jQuery.isFunction( options ) ) {
10147 options = options.call( elem, i, curOffset );
10148 }
10149
10150 if ( options.top != null ) {
10151 props.top = ( options.top - curOffset.top ) + curTop;
10152 }
10153 if ( options.left != null ) {
10154 props.left = ( options.left - curOffset.left ) + curLeft;
10155 }
10156
10157 if ( "using" in options ) {
10158 options.using.call( elem, props );
10159 } else {
10160 curElem.css( props );
10161 }
10162 }
10163};
10164
10165jQuery.fn.extend({
10166 offset: function( options ) {
10167 if ( arguments.length ) {
10168 return options === undefined ?
10169 this :
10170 this.each(function( i ) {
10171 jQuery.offset.setOffset( this, options, i );
10172 });
10173 }
10174
10175 var docElem, win,
10176 box = { top: 0, left: 0 },
10177 elem = this[ 0 ],
10178 doc = elem && elem.ownerDocument;
10179
10180 if ( !doc ) {
10181 return;
10182 }
10183
10184 docElem = doc.documentElement;
10185
10186 // Make sure it's not a disconnected DOM node
10187 if ( !jQuery.contains( docElem, elem ) ) {
10188 return box;
10189 }
10190
10191 // If we don't have gBCR, just use 0,0 rather than error
10192 // BlackBerry 5, iOS 3 (original iPhone)
10193 if ( typeof elem.getBoundingClientRect !== strundefined ) {
10194 box = elem.getBoundingClientRect();
10195 }
10196 win = getWindow( doc );
10197 return {
10198 top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
10199 left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
10200 };
10201 },
10202
10203 position: function() {
10204 if ( !this[ 0 ] ) {
10205 return;
10206 }
10207
10208 var offsetParent, offset,
10209 parentOffset = { top: 0, left: 0 },
10210 elem = this[ 0 ];
10211
10212 // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
10213 if ( jQuery.css( elem, "position" ) === "fixed" ) {
10214 // we assume that getBoundingClientRect is available when computed position is fixed
10215 offset = elem.getBoundingClientRect();
10216 } else {
10217 // Get *real* offsetParent
10218 offsetParent = this.offsetParent();
10219
10220 // Get correct offsets
10221 offset = this.offset();
10222 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
10223 parentOffset = offsetParent.offset();
10224 }
10225
10226 // Add offsetParent borders
10227 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
10228 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
10229 }
10230
10231 // Subtract parent offsets and element margins
10232 // note: when an element has margin: auto the offsetLeft and marginLeft
10233 // are the same in Safari causing offset.left to incorrectly be 0
10234 return {
10235 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
10236 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
10237 };
10238 },
10239
10240 offsetParent: function() {
10241 return this.map(function() {
10242 var offsetParent = this.offsetParent || docElem;
10243
10244 while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
10245 offsetParent = offsetParent.offsetParent;
10246 }
10247 return offsetParent || docElem;
10248 });
10249 }
10250});
10251
10252// Create scrollLeft and scrollTop methods
10253jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
10254 var top = /Y/.test( prop );
10255
10256 jQuery.fn[ method ] = function( val ) {
10257 return access( this, function( elem, method, val ) {
10258 var win = getWindow( elem );
10259
10260 if ( val === undefined ) {
10261 return win ? (prop in win) ? win[ prop ] :
10262 win.document.documentElement[ method ] :
10263 elem[ method ];
10264 }
10265
10266 if ( win ) {
10267 win.scrollTo(
10268 !top ? val : jQuery( win ).scrollLeft(),
10269 top ? val : jQuery( win ).scrollTop()
10270 );
10271
10272 } else {
10273 elem[ method ] = val;
10274 }
10275 }, method, val, arguments.length, null );
10276 };
10277});
10278
10279// Add the top/left cssHooks using jQuery.fn.position
10280// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
10281// getComputedStyle returns percent when specified for top/left/bottom/right
10282// rather than make the css module depend on the offset module, we just check for it here
10283jQuery.each( [ "top", "left" ], function( i, prop ) {
10284 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
10285 function( elem, computed ) {
10286 if ( computed ) {
10287 computed = curCSS( elem, prop );
10288 // if curCSS returns percentage, fallback to offset
10289 return rnumnonpx.test( computed ) ?
10290 jQuery( elem ).position()[ prop ] + "px" :
10291 computed;
10292 }
10293 }
10294 );
10295});
10296
10297
10298// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
10299jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
10300 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
10301 // margin is only for outerHeight, outerWidth
10302 jQuery.fn[ funcName ] = function( margin, value ) {
10303 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
10304 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
10305
10306 return access( this, function( elem, type, value ) {
10307 var doc;
10308
10309 if ( jQuery.isWindow( elem ) ) {
10310 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
10311 // isn't a whole lot we can do. See pull request at this URL for discussion:
10312 // https://github.com/jquery/jquery/pull/764
10313 return elem.document.documentElement[ "client" + name ];
10314 }
10315
10316 // Get document width or height
10317 if ( elem.nodeType === 9 ) {
10318 doc = elem.documentElement;
10319
10320 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
10321 // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
10322 return Math.max(
10323 elem.body[ "scroll" + name ], doc[ "scroll" + name ],
10324 elem.body[ "offset" + name ], doc[ "offset" + name ],
10325 doc[ "client" + name ]
10326 );
10327 }
10328
10329 return value === undefined ?
10330 // Get width or height on the element, requesting but not forcing parseFloat
10331 jQuery.css( elem, type, extra ) :
10332
10333 // Set width or height on the element
10334 jQuery.style( elem, type, value, extra );
10335 }, type, chainable ? margin : undefined, chainable, null );
10336 };
10337 });
10338});
10339
10340
10341// The number of elements contained in the matched element set
10342jQuery.fn.size = function() {
10343 return this.length;
10344};
10345
10346jQuery.fn.andSelf = jQuery.fn.addBack;
10347
10348
10349
10350
10351// Register as a named AMD module, since jQuery can be concatenated with other
10352// files that may use define, but not via a proper concatenation script that
10353// understands anonymous AMD modules. A named AMD is safest and most robust
10354// way to register. Lowercase jquery is used because AMD module names are
10355// derived from file names, and jQuery is normally delivered in a lowercase
10356// file name. Do this after creating the global so that if an AMD module wants
10357// to call noConflict to hide this version of jQuery, it will work.
10358
10359// Note that for maximum portability, libraries that are not jQuery should
10360// declare themselves as anonymous modules, and avoid setting a global if an
10361// AMD loader is present. jQuery is a special case. For more information, see
10362// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
10363
10364if ( typeof define === "function" && define.amd ) {
10365 define( "jquery", [], function() {
10366 return jQuery;
10367 });
10368}
10369
10370
10371
10372
10373var
10374 // Map over jQuery in case of overwrite
10375 _jQuery = window.jQuery,
10376
10377 // Map over the $ in case of overwrite
10378 _$ = window.$;
10379
10380jQuery.noConflict = function( deep ) {
10381 if ( window.$ === jQuery ) {
10382 window.$ = _$;
10383 }
10384
10385 if ( deep && window.jQuery === jQuery ) {
10386 window.jQuery = _jQuery;
10387 }
10388
10389 return jQuery;
10390};
10391
10392// Expose jQuery and $ identifiers, even in
10393// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
10394// and CommonJS for browser emulators (#13566)
10395if ( typeof noGlobal === strundefined ) {
10396 window.jQuery = window.$ = jQuery;
10397}
10398
10399
10400
10401
10402return jQuery;
10403
10404}));
10405 var validRegex = XRegExp('^((\\\\u00A3)|(\\\\u20AC)|([\\p{L}\\p{N}.\\-/+=_ !$*?@|&:\\u00A3\\u20AC\\n\\r\\[\\]]{0,1000}))$');
10406 var activateMinibag = true
10407</script>
10408
10409 <link rel="shortcut icon" href="https://images2.drct2u.com:443/repo/JDW/favicon/JDW-icon-48x48.ico?version=P-3-2020-01-07-WS-2020-01-V2&appversion=0" type="image/ico" />
10410<script type="text/javascript">
10411var jSIPT = 'signin';
10412var jSILT = '<a href="/shop/dispatcher.servlet?pageTo='+jSIPT+'" class="blacklink">Sign in</a> to access your account details and special offers.';
10413 var TITLE_NAME = 'J D Williams';
10414 var TITLE_URL = 'www.jdwilliams.co.uk';
10415 var ABUSE_EMAIL = 'abuse@jdwilliams.co.uk';
10416
10417 function jumpTo(url){
10418 if (((navigator.appName.indexOf("Microsoft") != -1) && (parseInt(navigator.appVersion) > 3.02)) || location.replace) {
10419 top.location.replace(url);
10420 } else {
10421 top.location.href = url;
10422 }
10423 }
10424 if( top != self ) {
10425 //now check for any internal frames
10426 externallyFramed = false;
10427 try {
10428 externallyFramed = top.location.host != location.host;
10429 } catch(err) {
10430 externallyFramed = true;
10431 }
10432 if(externallyFramed) {
10433 if (location.search.indexOf("redirect=1") >= 0) {
10434 alert("We have identified you are trying to access "+TITLE_URL+
10435 ". The site you have accessed is\nNOT "+TITLE_URL+
10436 " or any of its associated companies.\n\n"+
10437 "The address you are using is potentially dangerous and should NOT be used, we recommend you\nclose the browser and return to "+TITLE_NAME+
10438 " by our registered address of "+TITLE_URL+".\n\n"+
10439 TITLE_NAME+" will never ask customers to enter security or personal details into popup windows, if\nthere are any windows of this nature they do not originate from our website, Do not enter any\ninformation into these pages and please report this site to "+
10440 ABUSE_EMAIL+".");
10441 } else {
10442 var loc = self.location;
10443 var search = loc.search;
10444 if (search.length < 1) {
10445 search = "?redirect=1";
10446 } else {
10447 search += "&redirect=1";
10448 }
10449 var url = loc.protocol + "//" + loc.host + loc.pathname + search + loc.hash;
10450 jumpTo(url);
10451 }
10452 }
10453 }
10454</script>
10455
10456<!-- END standardHeaderItems --><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
10457 <link rel="stylesheet" type="text/css" href="https://images2.drct2u.com/dynamicPresentation/single/css/signin/responsive/style.css?single_type=css&version=P-3-2020-01-07-WS-2020-01-V2&minify=false&appversion=0" >
10458
10459 <script type="text/javascript">
10460
10461 var tagDataLayer = {"CategoryID":"CGN-SIGNIN-REG","PageTypeName":"signin-page","LoggedIn":false,"OrderID":"AJ_yJDFwxf5b4NxaiD2p6vK","autoLogin":false,"hashedAccountRef":"","DeviceType":"Smartphone","Currency":"GBP","MobileApp":true,"DeviceName":"Apple iPhone"};
10462 window.dataLayer = window.dataLayer || [];
10463 window.dataLayer.push({"CategoryID":"CGN-SIGNIN-REG","PageTypeName":"signin-page","LoggedIn":false,"OrderID":"AJ_yJDFwxf5b4NxaiD2p6vK","autoLogin":false,"hashedAccountRef":"","DeviceType":"Smartphone","Currency":"GBP","MobileApp":true,"DeviceName":"Apple iPhone"});
10464 $(document).ready(function () {
10465
10466 if(document.referrer.split('/')[2]!=location.hostname){
10467 $("#signInBackButton").hide();
10468 }else{
10469 $("#signInBackButton").show();
10470 }
10471
10472 });
10473 </script>
10474<!-- Google Tag Manager -->
10475
10476
10477
10478<noscript>
10479 <iframe src="//www.googletagmanager.com/ns.html?id=GTM-5R7HC5"
10480 height="0" width="0" style="display:none;visibility:hidden">
10481 </iframe>
10482</noscript>
10483<script>
10484 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
10485 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
10486 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
10487 '//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
10488 })(window,document,'script','dataLayer','GTM-5R7HC5');
10489</script>
10490<!-- End Google Tag Manager -->
10491<script>window.BOOMR_config = { Continuity: { enabled: true, waitAfterOnload: 3000 } };</script>
10492<script>!function(){function e(e){a.BOOMR_onload=e&&e.timeStamp||(new Date).getTime()}if(!window.BOOMR||!window.BOOMR.version){var t,n,o,i=document.createElement("iframe"),a=window;a.addEventListener?a.addEventListener("load",e,!1):a.attachEvent&&a.attachEvent("onload",e),i.src="javascript:void(0)",i.title="",i.role="presentation",(i.frameElement||i).style.cssText="width:0;height:0;border:0;display:none;",(o=document.getElementsByTagName("script")[0]).parentNode.insertBefore(i,o);try{n=i.contentWindow.document}catch(e){t=document.domain,i.src="javascript:var d=document.open();d.domain='"+t+"';void(0);",n=i.contentWindow.document}n.open()._l=function(){var e=this.createElement("script");t&&(this.domain=t),e.id="boomr-if-as",e.src="https://s.go-mpulse.net/boomerang/3F8AA-8PZ5U-YFL4G-5TWL8-T6YJV",BOOMR_lstart=(new Date).getTime(),this.body.appendChild(e)},n.write('<body onload="document._l();">'),n.close()}}();</script>
10493 <!-- Begin Monetate ExpressTag Sync v8. Place at start of document head. DO NOT ALTER. -->
10494 <script type="text/javascript">var monetateT = new Date().getTime();</script>
10495 <script type="text/javascript" src="//se.monetate.net/js/2/a-c450c8bc/p/jdwilliams.co.uk/entry.js">
10496 </script>
10497 <!-- End Monetate tag. -->
10498</head>
10499
10500 <body class="rwd-signin">
10501 <div id="googleAnalyticsContent"></div>
10502 <!--Start: Header-->
10503 <header class="main-header">
10504 <section>
10505 <div class="registerLogoWrap">
10506 <a id="signInBackButton" href="javascript:history.go(-1);" class="gui-btn gui-btn-tertiary bordered" title="go back and continue shopping">
10507 <div class="gui-btn-inner">Back</div>
10508 </a>
10509 </div>
10510 <div class="logo">
10511 <a name="Home" href="/" title="Homepage">
10512 <img src="https://images2.drct2u.com:443/repo/JDW/desktop/responsiveheader/02-images/logo-JDW.svg" id="CHKT-BRAND-LOGO" href="javascript:void(0)" title="J D Williams">
10513 </a>
10514 </div>
10515 </section>
10516 </header>
10517 <!--Finish: Header-->
10518 <section class="main">
10519 <div class="sign-in-form-wrapper">
10520
10521
10522<script type="text/javascript" src="https://images2.drct2u.com/content/javascript/jdw_acctvalid.js?version=P-3-2020-01-07-WS-2020-01-V2&appversion=0"></script><script type="text/javascript" src="https://images2.drct2u.com/content/javascript/jdw_formhelper.js?version=P-3-2020-01-07-WS-2020-01-V2&appversion=0"></script><script type="text/javascript" src="https://images2.drct2u.com/content/javascript/registration/jquery.livequery.js?version=P-3-2020-01-07-WS-2020-01-V2&appversion=0"></script><script type="text/javascript" src="https://images2.drct2u.com/content/javascript/jdw_helpHover.js?version=P-3-2020-01-07-WS-2020-01-V2&appversion=0"></script><script type="text/javascript" src="https://images2.drct2u.com/content/javascript/jdw_popup.js?version=P-3-2020-01-07-WS-2020-01-V2&appversion=0"></script>
10523
10524
10525<script type="text/javascript" src="https://images2.drct2u.com/content/javascript/i18n/en/validationMessages.js?version=P-3-2020-01-07-WS-2020-01-V2&appversion=0"></script><script language="javascript" type="text/javascript">
10526 var strErrorMessage= 'Email \/ Account No. or Password is incorrect.<br\/> All passwords are CASE SENSITIVE.';
10527 var nonModalHelpText = "Enter your customer account number (e.g A1234567) or Email Address below along with your password to sign in. Your account number can be found on the statements or delivery notes.";
10528
10529 function displayErrorMessage(strErrorMsg, fields) {
10530 removeAllErrorMsgs();
10531
10532 //$('#'+fields[0]).focus();
10533 $('#password').val('');
10534
10535 if(strErrorMsg!=''){
10536 if( fields.length == 1 ) {
10537 showErrorHover([fields[0]], strErrorMsg, 0);
10538 } else {
10539 if( strErrorMsg.length == fields.length ) {
10540 for(var i=0; i<fields.length;i++) {
10541 showErrorHover([fields[i]], strErrorMsg[i], i);
10542 }
10543 } else {
10544 showErrorHover(fields, strErrorMsg);
10545 }
10546 }
10547
10548 for(var i=0; i<fields.length;i++) {
10549 var fieldId = fields[i];
10550 $('#' + fieldId).addClass('signInError');
10551 }
10552 }
10553 }
10554
10555 // Check for enter being hit and submit if the case
10556 function processKeyPress(event) {
10557 if (!event) var event = window.event();
10558 if (event.keyCode == 13 || event.charCode == 13) {
10559 dosubmit();
10560 }
10561 }
10562
10563 function handleAjaxSignin(returnObj) {
10564 var signedIn = returnObj.fullySignedIn;
10565
10566 if(signedIn==true) {
10567 var displayViewBag = returnObj.displayViewBag;
10568 if(displayViewBag==true) {
10569 redirectRequired=true;
10570 redirectURL='/shop/viewbag/ViewBag.action';
10571 }
10572 closeModalJQ();
10573 } else {
10574 displayErrorMessage(returnObj.errorMessage,['accountNumber','password']);
10575 }
10576 }
10577
10578 function dosubmit() {
10579 if((typeof(Storage) !== "undefined") && document.referrer) {
10580 try {
10581 sessionStorage.setItem("previousUrl", document.referrer);
10582 } catch (e) {
10583 }
10584 }
10585
10586 $(".signInError").each(function(){
10587 $(this).removeClass('signInError');
10588 });
10589
10590 if (isEmpty(document.signinForm.accountRefOrEmail.value)) {
10591 var message = true ? accountNumberEmailMissingMsg : accountNumberlengthvalidationmsg;
10592 if( isEmpty(document.signinForm.password.value )) {
10593 displayErrorMessage([message,enterPasswordValMsg],['accountNumber', 'password']);
10594 } else {
10595 displayErrorMessage(message,['accountNumber']);
10596 }
10597 } else if (!checkSigninIdFormat(document.signinForm.accountRefOrEmail.value, true)) {
10598 var message = true ? accountNumberEmailInvalidMsg : accountNumberlengthvalidationmsg;
10599 if( isEmpty(document.signinForm.password.value )) {
10600 displayErrorMessage([message,enterPasswordValMsg],['accountNumber', 'password']);
10601 } else {
10602 displayErrorMessage(message,['accountNumber']);
10603 }
10604 } else if (isEmpty(document.signinForm.password.value)) {
10605 displayErrorMessage(enterPasswordValMsg,['password']);
10606 } else {
10607 var modal = 'false';
10608 if(modal=='true') {
10609 var formData = $('#signinForm').serializeArray();
10610 performAjaxRequest('/shop/signin/modal/process.action',null,null,'json',formData,
10611 handleAjaxSignin,null,'POST','overlayContainer', null);
10612 } else {
10613 document.signinForm.submit();
10614 }
10615 }
10616 }
10617 function showErrorHover(fieldId, text, id) {
10618 var errorHoverDivId = "errorHoverDiv"+id
10619 $('body').append('<div id='+errorHoverDivId+' class="signInErrorTip">'+'<p>'+text+'</p></div>');
10620
10621 var position, leftOffset, topOffset, leftPosition, topPosition;
10622
10623 $(window).ready(function() {
10624 $('#'+errorHoverDivId).insertAfter('#'+fieldId);
10625 });
10626 }
10627
10628 $(document).ready(function(){
10629 removeAllErrorMsgs();
10630 displayErrorMessage(strErrorMessage,['accountNumber','password']);
10631 if(strErrorMessage=='') {
10632 $('#accountNumber').focus();
10633 }
10634
10635 });
10636
10637 function forgottenDetails(type) {
10638 if('false'=='true') {
10639 getMessageResources('checkout/actions/package', null, '/shop/util/', true);
10640 var navAwayMsg = STRINGS['navigate.away.message.forgotten'];
10641 window.onbeforeunload = function() {
10642 return navAwayMsg;
10643 };
10644 }
10645
10646 if(type=='account') {
10647 window.location.href='/shop/dispatcher.servlet?pageTo=forgottenAcctNum';
10648 } else {
10649 window.location.href='/shop/dispatcher.servlet?pageTo=forgottenPassword';
10650 }
10651 }
10652 function removeAllErrorMsgs() {
10653 $("div[id^='errorHoverDiv']").each(function () {
10654 $(this).remove();
10655 });
10656 }
10657</script>
10658<div class="signInExistingWrapper one-half primary vertical-center-content" id="existingCustomerPanel">
10659 <div style="display: none;" name="SIStatus" id="SIStatus">102</div>
10660 <div class="inner">
10661<form id="signinForm" name="signinForm" action="/shop/signin/process.action" method="post" class="signinForm" class="class java.util.HashMap">
10662 <h2 class="title">Sign In</h2>
10663
10664 <div class="signInContainer">
10665
10666 <div class="signInEmailFormContainer">
10667 <div class="input-wrapper">
10668 <label for="accountNumber" id="accountNumberLabel" class="element-invisible">Email Address OR Account Number</label>
10669 <input name="accountRefOrEmail" type="text" id="accountNumber" placeholder="Email Address OR Account Number" onkeypress="javascript:processKeyPress(event);" value="" maxlength="100">
10670<!--
10671 <a helptext="Enter your customer account number (e.g A1234567) or Email Address below along with your password to sign in. Your account number can be found on the statements or delivery notes." helptitle="Returning Customer" id="emailAddressFieldHelp" class="help">Help</a>
10672 -->
10673 <div class="form-link-wrapper clearfix">
10674 <a class="signInLinks form-link" onclick="javascript:forgottenDetails('account');" tabindex="998" href="javascript:void(0);">Forgot Your Account Number?</a>
10675 </div>
10676 </div>
10677 </div>
10678
10679 <div class="signInPasswordContainer">
10680 <div class="input-wrapper">
10681 <label for="password" id="passwordLabel" class="element-invisible">Password</label>
10682 <input name="password" type="password" id="password" placeholder="Password" onkeypress="javascript:processKeyPress(event);" size="60" autocomplete="off">
10683 <div class="form-link-wrapper clearfix">
10684 <a class="signInLinks form-link" onclick="javascript:forgottenDetails('password');" tabindex="998" href="javascript:void(0);">Forgot Your Password?</a>
10685 </div>
10686 </div>
10687 </div>
10688 <div class="signInContinueContainer">
10689 <div class="signInButtonAreaLeft">
10690 <div class="signInButtonContainer">
10691 <a class="signInButton btn primaryBtn icon-secure" onclick="javascript:dosubmit();" href="javascript:void(0);">Sign In</a>
10692 </div>
10693 </div>
10694 </div>
10695<input type="hidden" name="csrfRandomFormToken" value="91be4d0d-5beb-4019-9f7d-80ef4060c089" id="csrfRandomFormToken"/><input type="hidden" name="isMobileApp" value="true" id="isMobileApp"/></form>
10696
10697
10698
10699 </div>
10700</div>
10701</div>
10702
10703<div class="newCustomerContainer one-half secondary vertical-center-content">
10704 <div class="inner">
10705
10706 <form class="new-customer">
10707 <div>
10708
10709 <a href="/shop/responsiveRegistration/start.action" class="btnContinue btn secondaryBtn icon-rightarrow">new Online Customer</span></a>
10710
10711 </div>
10712 </form>
10713
10714 </div>
10715</div>
10716<script>
10717<!--
10718 var inCheckout = false;
10719
10720 function webEnableExistingCustomer() {
10721 window.onbeforeunload = null;
10722 window.location.href='/shop/dispatcher.servlet?pageTo=forgottenPassword';
10723 if(inCheckout) {
10724 window.location.href='/shop/webenable/showPersonalDetails.action?inCheckout=true';
10725 } else {
10726 window.location.href='/shop/webenable/showPersonalDetails.action';
10727 }
10728 }
10729-->
10730</script> </div>
10731 </section>
10732 <!--.main-footer-->
10733 <footer class="main-footer">
10734 <p class="helpText">Need Help? Got a Question? <br>Give us a call on <span class="helpNumber secondary">0871 231 2000</span> <br><span class="legal-sub">(Calls cost 13p per minute plus your phone company’s access charge)</span></p>
10735 </footer>
10736 <!--/.main-footer-->
10737
10738<!-- RESPONSIVE FOOTER -->
10739<footer class="globalFooter" id="footer">
10740 <div class="logoContainer">
10741 <div class="bazaarVoiceSellerRatings">
10742 <img src="https://display.ugc.bazaarvoice.com/common/images/trustmark_icons/trustmark_en.png" />
10743 <!-- Bazaar Voice Insert -->
10744 <script src="https://apps.bazaarvoice.com/deployments/jd-williams/main_site/production/en_GB/bv.js"></script>
10745 <div id="BVSellerRatingsContainer"></div>
10746 <script>BV.seller_ratings.render();</script>
10747 <!-- END Bazaar Voice Insert -->
10748 </div>
10749 <div class="nortonSecured">
10750 <iframe frameborder="0" scrolling="no" width="115" height="75" src="/shop/verisign.jsp"></iframe>
10751 </div>
10752 </div>
10753</footer>
10754
10755<!-- Display cookie policy banner at the top of the page. -->
10756<!-- Cookie policy -->
10757 <script defer type="text/javascript" src="https://images2.drct2u.com/dynamicPresentation/single/javascript/mobile/cookiepolicy/cookiepolicy.js?single_type=js&version=P-3-2020-01-07-WS-2020-01-V2&minify=true&appversion=0"></script>
10758<div id="cookieBannerWrapper" class="cookieBannerWrapper">
10759 <div id="cookieBanner" class="cookieBanner">
10760 <div class="cookieBannerTextContainer">
10761 <h6>We use cookies to give you the best possible user experience.</h6>
10762 <p>If you continue, we assume that you consent to receive all cookies on all our websites. You can find out more information about cookies <a href="/shop/page/cookies/show.action" target="_blank">here</a>.</p>
10763 </div>
10764 <a href="#" id="cookiepolicyClose">
10765 <div class="closeBtn">Close</div>
10766 </a>
10767 <a href="#" id="cookiepolicyOk">
10768 <div class="okBtn">OK</div>
10769 </a>
10770 <noscript>
10771 <style type="text/css">
10772 <!--
10773 body { padding-top: 70px; }
10774 #cookiepolicyClose { display: none; }
10775 #cookieBannerWrapper { display: block; height: 70px; }
10776 -->
10777 </style>
10778 </noscript>
10779 </div>
10780</div>
10781<script>
10782 var c_enabled = true;
10783</script>
10784
10785<!--BEGIN_EXCLUDE--> <script type="text/javascript" src="https://images2.drct2u.com/dynamicPresentation/single/javascript/common/libraries/celebrus/celebrusInsert.js?single_type=js&version=P-3-2020-01-07-WS-2020-01-V2&minify=true&appversion=0"></script>
10786<!--END_EXCLUDE-->
10787
10788<script type="text/javascript">
10789jQuery(document).ready(function($) {
10790 "use strict";
10791 var btnEireSigninCollapse = $('.newCustomerContainer').delegate('a[data-collapse-info]', 'click', function () {
10792 var btnLink = $(this);
10793 var content = btnLink.closest('.new-customer').find('.collapse-content');
10794 content.slideToggle(300);
10795 });
10796});jQuery.url=function(){var segments={};var parsed={};var options={url:window.location,strictMode:false,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};var parseUri=function(){str=decodeURI(options.url);var m=options.parser[options.strictMode?"strict":"loose"].exec(str);var uri={};var i=14;while(i--){uri[options.key[i]]=m[i]||""}uri[options.q.name]={};uri[options.key[12]].replace(options.q.parser,function($0,$1,$2){if($1){uri[options.q.name][$1]=$2}});return uri};var key=function(key){if(!parsed.length){setUp()}if(key=="base"){if(parsed.port!==null&&parsed.port!==""){return parsed.protocol+"://"+parsed.host+":"+parsed.port+"/"}else{return parsed.protocol+"://"+parsed.host+"/"}}return(parsed[key]==="")?null:parsed[key]};var param=function(item){if(!parsed.length){setUp()}return(parsed.queryKey[item]===null)?null:parsed.queryKey[item]};var setUp=function(){parsed=parseUri();getSegments()};var getSegments=function(){var p=parsed.path;segments=[];segments=parsed.path.length==1?{}:(p.charAt(p.length-1)=="/"?p.substring(1,p.length-1):path=p.substring(1)).split("/")};return{setMode:function(mode){strictMode=mode=="strict"?true:false;return this},setUrl:function(newUri){options.url=newUri===undefined?window.location:newUri;setUp();return this},segment:function(pos){if(!parsed.length){setUp()}if(pos===undefined){return segments.length}return(segments[pos]===""||segments[pos]===undefined)?null:segments[pos]},attr:key,param:param}}();/**
10797 * Cookie plugin
10798 *
10799 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
10800 * Dual licensed under the MIT and GPL licenses:
10801 * http://www.opensource.org/licenses/mit-license.php
10802 * http://www.gnu.org/licenses/gpl.html
10803 *
10804 */
10805
10806/**
10807 * Create a cookie with the given name and value and other optional parameters.
10808 *
10809 * @example $.cookie('the_cookie', 'the_value');
10810 * @desc Set the value of a cookie.
10811 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
10812 * @desc Create a cookie with all available options.
10813 * @example $.cookie('the_cookie', 'the_value');
10814 * @desc Create a session cookie.
10815 * @example $.cookie('the_cookie', null);
10816 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
10817 * used when the cookie was set.
10818 *
10819 * @param String name The name of the cookie.
10820 * @param String value The value of the cookie.
10821 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
10822 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
10823 * If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
10824 * If set to null or omitted, the cookie will be a session cookie and will not be retained
10825 * when the the browser exits.
10826 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
10827 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
10828 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
10829 * require a secure protocol (like HTTPS).
10830 * @type undefined
10831 *
10832 * @name $.cookie
10833 * @cat Plugins/Cookie
10834 * @author Klaus Hartl/klaus.hartl@stilbuero.de
10835 */
10836
10837/**
10838 * Get the value of a cookie with the given name.
10839 *
10840 * @example $.cookie('the_cookie');
10841 * @desc Get the value of a cookie.
10842 *
10843 * @param String name The name of the cookie.
10844 * @return The value of the cookie.
10845 * @type String
10846 *
10847 * @name $.cookie
10848 * @cat Plugins/Cookie
10849 * @author Klaus Hartl/klaus.hartl@stilbuero.de
10850 */
10851jQuery.cookie = function(name, value, options) {
10852 if (typeof value != 'undefined') { // name and value given, set cookie
10853 options = options || {};
10854 if (value === null) {
10855 value = '';
10856 options.expires = -1;
10857 }
10858 var expires = '';
10859 if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
10860 var date;
10861 if (typeof options.expires == 'number') {
10862 date = new Date();
10863 date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
10864 } else {
10865 date = options.expires;
10866 }
10867 expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
10868 }
10869 // CAUTION: Needed to parenthesize options.path and options.domain
10870 // in the following expressions, otherwise they evaluate to undefined
10871 // in the packed version for some reason...
10872 var path = options.path ? '; path=' + (options.path) : '';
10873 var domain = options.domain ? '; domain=' + (options.domain) : '';
10874 var secure = options.secure ? '; secure' : '';
10875 document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
10876 } else { // only name given, get cookie
10877 var cookieValue = null;
10878 if (document.cookie && document.cookie != '') {
10879 var cookies = document.cookie.split(';');
10880 for (var i = 0; i < cookies.length; i++) {
10881 var cookie = jQuery.trim(cookies[i]);
10882 // Does this cookie string begin with the name we want?
10883 if (cookie.substring(0, name.length + 1) == (name + '=')) {
10884 cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
10885 break;
10886 }
10887 }
10888 }
10889 return cookieValue;
10890 }
10891};$.fn.Sleep = function(duration, callback) {
10892 if(!callback)callback=function(){return false;};
10893 $(this).animate({dummy:1}, duration, callback);
10894 return this;
10895};
10896
10897var modalLinkStack=[];
10898
10899var modalDefaults = {
10900 delay: 300,
10901 width : 500,
10902 height: 300,
10903 controlsHeight: 50,
10904 headerHeight: 50,
10905 scrollTop: 60,
10906 controls : '',
10907 closeDefault : '<div class="modalButtonClose modalButtonCloseFooter"><div class="modalButton"><div class="buttonCapLt"></div><a href="#" alt="Click to close this window" title="Click to close this window">Close this window</a><div class="buttonCapRt"></div></div></div>',
10908 backDefault : '<div class="modalButtonBack" id="modalButtonLeft" style="display:none;"><div class="modalButton"><div class="buttonCapLt"></div><a id="modalBackAnchor" href="#" alt="Click to Go Back" title="Click to go back">Back</a><div class="buttonCapRt"></div></div></div>',
10909 overlayClose : 'true',
10910 backButton : 'true',
10911 nonModal: 'false'
10912};
10913
10914var modalFunctions = {
10915 create : {
10916 container : function (data, showScrollbars, options) {
10917 var new_overlay = 0;
10918 if($('#modal_overlay').size() == 0) {
10919 $('body').append('<div id="modal_overlay" style="display: none"></div>');
10920 $('body').append('<div id="modal_coremetrics_node" style="display: none"></div>');
10921 $('body').append('<div id="modal_outer" style="display: none"></div>');
10922 $('#modal_outer').append('<div id="modal_container" class="displayOverlay modal_container">' + data + '</div>');
10923 var new_overlay = 1;
10924 } else {
10925 $('#modal_outer').find('#modal_container').html(data);
10926 }
10927
10928 $('#modal_overlay').css({'width':'100%'});
10929
10930 var modalParam = $('#modal_outer').find('#modalParam');
10931
10932 if($('#modal_outer').find('#modalParam').attr('title'))
10933 modalDefaults.title = modalParam.attr('title');
10934 if($('#modal_outer').find('#modalParam').attr('overlayClose'))
10935 modalDefaults.overlayClose = modalParam.attr('overlayClose');
10936 if($('#modal_outer').find('#modalParam').attr('backButton'))
10937 modalDefaults.backButton = modalParam.attr('backButton');
10938 if($('#modal_outer').find('#modalParam').attr('nonModal'))
10939 modalDefaults.nonModal = modalParam.attr('nonModal');
10940 if($('#modal_outer').find('#modalParam').attr('width'))
10941 modalDefaults.width = modalParam.attr('width');
10942 if($('#modal_outer').find('#modalParam').attr('height'))
10943 modalDefaults.height = modalParam.attr('height');
10944 if($('#modal_outer').find('#modalParam').attr('controlsHeight'))
10945 modalDefaults.controlsHeight = modalParam.attr('controlsHeight');
10946 if($('#modal_outer').find('#modalParam').attr('scrollTopValue')) {
10947 modalDefaults.scrollTop = parseInt(modalParam.attr('scrollTopValue'));
10948 }
10949
10950 if(options && options.height) {
10951 modalDefaults.height = options.height;
10952 }if(options && options.width) {
10953 modalDefaults.width = options.width;
10954 }
10955
10956 var marginLeft;
10957 if($('#modal_outer').find('#modalParam').attr('marginLeft')){
10958 marginLeft = parseInt(modalParam.attr('marginLeft'));
10959 } else {
10960 marginLeft = -(modalDefaults.width/2);
10961 }
10962
10963 var outerHeight = parseInt(modalDefaults.height) + parseInt(modalDefaults.controlsHeight) + parseInt(modalDefaults.headerHeight);
10964 $('#modal_outer').css({'height': outerHeight + 'px','margin-left' : marginLeft + 'px', 'margin-top' : '-' + (outerHeight/2) + 'px'});
10965 $('#modal_outer').css({'position':'absolute', 'top': ($(window).scrollTop() + modalDefaults.scrollTop)+'px', 'marginTop': '0px'})
10966
10967 var overflow = 'hidden';
10968 if(showScrollbars) {
10969 overflow = 'auto';
10970 }
10971 var backgroundColor = $('#modal_outer').find('#modal_container').css("backgroundColor");
10972 if($('#modal_outer').find('#modalParam').attr('backgroundColor')) {
10973 backgroundColor = modalParam.attr('backgroundColor');
10974 }
10975 var border = $('#modal_outer').find('#modal_container').css("border")
10976 if($('#modal_outer').find('#modalParam').attr('border')) {
10977 border = modalParam.attr('border');
10978 }
10979 var height = $(document).height();
10980 $('#modal_overlay').css({'position':'absolute', 'height': height});
10981
10982 var modalContainer = $('#modal_outer').find('#modal_container');
10983 if ( typeof border != 'undefined' ){
10984 modalContainer.css({'height': (modalDefaults.height-20) + 'px', 'width': (modalDefaults.width-20) + 'px', 'overflow': overflow, 'backgroundColor': backgroundColor, 'border': border + 'px'});
10985 } else {
10986 modalContainer.css({'height': (modalDefaults.height-20) + 'px', 'width': (modalDefaults.width-20) + 'px', 'overflow': overflow, 'backgroundColor': backgroundColor});
10987 }
10988
10989 }, header : function (options) {
10990
10991 var hideHeader = options ? options.hideHeader : false;
10992 if(!hideHeader) {
10993 if($('#modal_outer').find('#modal_header').size() == 0) {
10994 if ( typeof modalDefaults.title != 'undefined' ){
10995 $('#modal_outer').prepend('<div id="modal_header"><p class="title"></p></div>');
10996 } else {
10997 $('#modal_outer').prepend('<div id="modal_header"></div>');
10998 }
10999
11000 if(options && options.closeButtonHeader) {
11001 $('#modal_header').append('<div class="modalButtonClose"><div class="buttonCapLt"></div><a style="cursor:pointer;">Close this window</a><div class="buttonCapRt"></div></div>');
11002 }
11003
11004 if ( typeof modalDefaults.title != 'undefined' ){
11005 $('#modal_outer').find('#modal_header').find('.title').html(modalDefaults.title);
11006 }
11007 $('#modal_outer').find('#modal_header').css({'width': (modalDefaults.width-12) + 'px'});
11008 }
11009 }
11010 }, footer : function(options) {
11011
11012 var hideFooter = options ? options.hideFooter : false;
11013 if(!hideFooter) {
11014 modalDefaults.controls = modalFunctions.getModalControls(options);
11015
11016 if($('#modal_outer').find('#controls').html()) {
11017 modalDefaults.controls = $('#modal_outer').find('#controls').html();
11018 $('#modal_outer').find('#controls').remove();
11019 }
11020
11021 if($('#modal_outer').find('#modal_control').size() == 1)
11022 $('#modal_outer').find('#modal_control').remove();
11023
11024 $('#modal_outer').append('<div id="modal_control">' + modalDefaults.controls + '</div>');
11025 $('#modal_outer').find('#modal_control').css({'width': (modalDefaults.width-20) + 'px'});
11026 }
11027 }, closeBtn : function (options) {
11028 var disableClose = options ? options.disableClose : false;
11029 if (modalDefaults.overlayClose == 'false' || disableClose) {
11030 $('.modalButtonClose').hide();
11031 }
11032 if(options && !options.closeButtonFooter) {
11033 $('.modalButtonCloseFooter').hide();
11034 }
11035 }, backBtn : function (disableClose, showScrollbars) {
11036 if (modalLinkStack.length > 1 && modalDefaults.backButton=='true'){
11037 var options = {
11038 fromBack: true,
11039 scrollbars: showScrollbars,
11040 closeButtonFooter: !disableClose
11041 };
11042 $('#modalBackAnchor').attr("modalBack", true);
11043 $('#modalBackAnchor').click(function() {
11044 jdwModal.displayModalFromUrl(modalLinkStack[modalLinkStack.length - 2], options);
11045 });
11046 //fade in
11047 $('.modalButtonBack').show();
11048 }
11049 }
11050 }, executeModal : function (data, disableClose, showScrollbars, options) {
11051 if (getIEVersionNumber() <= 6) {
11052 setSelects("hidden");
11053 }
11054
11055 if($('#modal_outer').find('#modal_container').size() == 1) {
11056 $('#modal_overlay').animate({opacity: 0.7}, 200, function () {
11057 $('#modal_overlay').animate({opacity: 0.8}, 200);
11058 });
11059
11060 this.create.container(data, showScrollbars, options);
11061
11062 modalDefaults.controls = modalFunctions.getModalControls(options);
11063
11064 if($('#modal_outer').find('#modal_container').find('#controls').html()) {
11065 modalDefaults.controls = $('#modal_outer').find('#modal_container').find('#controls').html();
11066 $('#modal_outer #modal_container #controls').fadeIn();
11067 }
11068
11069 if(!options || !options.hideFooter) {
11070 $('#modal_outer').find('#modal_control').html(modalDefaults.controls);
11071 }
11072
11073 this.create.header(options);
11074 $('#modal_outer').find('#modal_control').remove();
11075 this.create.footer(options);
11076 this.create.closeBtn(options);
11077 this.create.backBtn(disableClose, showScrollbars);
11078 } else {
11079 this.create.container(data, showScrollbars,options);
11080 this.create.header(options);
11081 this.create.footer(options);
11082 this.create.closeBtn(options);
11083
11084 if (typeof onPCMPage != 'undefined') {
11085 setTimeout(function() {
11086 $('#modal_overlay, #modal_outer').animate({opacity: 'show'}, 10, function () {
11087 $('#modal_overlay').animate({opacity: 0.8}, 350, 'linear', function(){
11088 $('.modalLoadFocus').first().focus();
11089 // Amplience workaround, adding a callback function is the long term solution
11090 $("#fitting").cssDropdown();
11091 $("#optionColourSelect").cssDropdown();
11092 $("#optionSizeSelect").cssDropdown();
11093 });
11094 });
11095 }, 500);
11096 } else {
11097 setTimeout(function() {
11098 $('#modal_overlay, #modal_outer').animate({opacity: 'show'}, 10, function () {
11099 $('#modal_overlay').animate({opacity: 0.8}, 350, 'linear', function(){$('.modalLoadFocus').first().focus();});
11100 });
11101 }, 500);
11102 }
11103 }
11104
11105
11106 $('#modal_outer #modal_container').scrollTop(0);
11107
11108 if(options && options.onSuccess) {
11109 options.onSuccess();
11110 }
11111
11112 }, getModalControls : function(options) {
11113
11114 var continueUrl;
11115 var continueText;
11116 var nextButton;
11117 var backButton = modalDefaults.backDefault;;
11118 var continueButton;
11119 var closeButton = modalDefaults.closeDefault;
11120
11121 if(options) {
11122 continueUrl = (options.continueUrl ? options.continueUrl : null);
11123 continueText = (options.continueText ? options.continueText : 'Continue');
11124
11125 if(options.backText) {
11126 backButton = '<div class="modalButtonBack" id="modalButtonLeft" style="display:none;">' +
11127 '<div class="modalButton"><div class="buttonCapLt"></div><a id="modalBackAnchor" ' +
11128 'href="#" alt="Click to Go Back" title="Click to go back">' + options.backText + '</a>' +
11129 '<div class="buttonCapRt"></div></div></div>';
11130 }
11131
11132 if(continueUrl) {
11133 continueButton = '<div class="btn primaryBtn icon-tick" id="modalButtonRight"><div class="modalButton">' +
11134 '<div class="buttonCapLt"></div><a id="modalContinueAnchor" ' +
11135 'onclick="'+ continueUrl + '"' +
11136 ' alt="Click to move forward" title="Click to move forward">' + continueText +
11137 '</a><div class="buttonCapRt"></div></div></div>';
11138 }
11139
11140 if(options.closeText) {
11141 closeButton = '<div class="modalButtonClose" id="modalButtonLeft">' +
11142 '<div class="modalButton"><div class="buttonCapLt"></div><a id="modalBackAnchor" ' +
11143 'href="#" alt="Click to close" title="Click to close">' + options.closeText + '</a>' +
11144 '<div class="buttonCapRt"></div></div></div>';
11145 }
11146 }
11147
11148 var controls;
11149 if(backButton)
11150 controls = backButton;
11151
11152 if(continueButton)
11153 controls+=continueButton;
11154
11155 if(closeButton)
11156 controls+=closeButton;
11157
11158 return controls;
11159 }
11160}
11161
11162function getIEVersionNumber() {
11163 if (/MSIE\s(\d+\.\d+);/.test(navigator.userAgent)) {
11164 return new Number(RegExp.$1);
11165 } else {
11166 return 999;
11167 }
11168}
11169
11170function setSelects(visibility) {
11171 selects = document.getElementsByTagName('select');
11172 for(i = 0; i < selects.length; i++) {
11173 selects[i].style.visibility = visibility;
11174 }
11175}
11176
11177function openModalJQ(data, url, fromBack, disableClose, showScrollbars, options) {
11178 reset();
11179 if(url)
11180 updateLinkStack(url, fromBack);
11181
11182 modalFunctions.executeModal(data, disableClose, showScrollbars, options);
11183
11184 return false;
11185}
11186
11187var closeModalDuration = 350;
11188function closeModalJQ() {
11189 $('#modal_overlay, #modal_outer').animate({opacity:'hide'}, closeModalDuration, function () { $(this).remove(); });
11190 if (getIEVersionNumber() <= 6) {
11191 setSelects("visible");
11192 }
11193
11194 setTimeout(function () {
11195 if(typeof yourvar != 'undefined' && jdwModalOptions.onClose) {
11196 jdwModalOptions.onClose();
11197 }
11198
11199 // clear stored links
11200 modalLinkStack = [];
11201 jdwModalOptions = {};
11202 }, closeModalDuration + 500);
11203}
11204
11205function enableCloseModalJQByClickingOutsideBorder(callBack) {
11206 /* Close overlay by clicking anywhere outside it's borders do this here so
11207 when you close the overlay you go back to the home page. */
11208 $('body').on('click', callBack, window.clickAnyWhereClickHandler);
11209}
11210
11211function clickAnyWhereClickHandler(e){ // Add new event handler
11212 if($('#modal_overlay').size()!=0 && $(e.target).closest('.orderContainer').length==0){
11213 $('body').die('click', window.clickAnyWhereClickHandler); // Unbind default event handler defined in jdw_ajax.js
11214 closeModalJQ();
11215 //The call back function name is passed in as a string,
11216 //so the .on() function does not execute with 2 params, but uses 3 params.
11217 var clickAnyWhereCallBack = e.data;
11218 if (clickAnyWhereCallBack) {
11219 eval(clickAnyWhereCallBack + "()");
11220 }
11221 }
11222}
11223
11224function disableCloseModalJQByClickingOutsideBorder(){
11225 $('body').die('click', window.clickAnyWhereClickHandler);
11226}
11227
11228function updateLinkStack(url,fromBack){
11229 // if not modal back button
11230 if (url && !fromBack) {
11231 pushLink(url);
11232 } else if(fromBack) {
11233 popLink();
11234 }
11235}
11236
11237function pushLink(url) {
11238 //push link onto stack
11239 if(modalLinkStack.length==0){
11240 modalLinkStack[0] = url;
11241 }else{
11242 modalLinkStack[modalLinkStack.length] = url;
11243 }
11244}
11245
11246function popLink(){
11247 //pop link from stack
11248 modalLinkStack.splice(modalLinkStack.length - 1,1);
11249}
11250
11251function reset(){
11252 modalDefaults.backButton='true';
11253 modalDefaults.overlayClose='true';
11254 modalDefaults.nonModal='false';
11255}
11256
11257$(document).on('click', '.modalButtonClose', function(event){
11258 event.preventDefault();
11259 closeModalJQ();
11260
11261 var onCloseFunctionName = $(this).attr('onClose');
11262 if ( onCloseFunctionName ) {
11263 eval( onCloseFunctionName + '()' );
11264 }
11265});
11266
11267$(window).resize(function(){
11268 $('#modal_outer, #prodImageZoomify').css({'position':'absolute', 'top': ($(window).scrollTop() + 60)+'px', 'marginTop': '0px'})
11269
11270 var height = $(document).height();
11271 var width = $(document).width();
11272 $('#modal_overlay').css({'position':'absolute', 'height': height, 'width' : width });
11273});
11274
11275function checkForRedirect(xmlHttpRequest) {
11276 var redirectUrl = xmlHttpRequest.getResponseHeader('REDIRECT_URL');
11277 if (redirectUrl == null || redirectUrl.length == 0) {
11278 return true;
11279 } else {
11280 location.href = redirectUrl;
11281 }
11282}
11283
11284function getUniqueClass(selected) {
11285 var uniqueID = new Date().getTime() + "Class";
11286 $(selected).addClass(uniqueID);
11287
11288 return uniqueID;
11289}
11290
11291function ajaxGet(selected, successCallback, url) {
11292
11293 if (!url) {
11294 var url = $(selected).attr('href');
11295 }
11296
11297 if (!successCallback.hideUpdatingOverlay) {
11298 overlay.create({'msg':'Updating', 'showDelay' : 1000, 'trigger': getUniqueClass(selected)});
11299 }
11300
11301 var xhtmlRequest = $.get(url, function (data) {
11302 closedelay = overlay.closeOverlay();
11303 if (checkForRedirect(xhtmlRequest)) {
11304 successCallback(data);
11305 }
11306 });
11307}
11308
11309var closedelay;
11310
11311function performAjaxRequest( urlString, beforeSendFunction, onCompleteFunction, dataType, data,
11312 onSuccessFunction, onErrorFunction, sendMethod, triggerData,
11313 sessionTimeoutFunction ) {
11314 var xhtmlRequest;
11315 var createUpdatingOverlay = true;
11316
11317 // Default blank value of sendMethod to explicitly say 'GET' as a blank value seems to upset the
11318 // android browser.
11319 if(!sendMethod) {
11320 sendMethod = 'GET';
11321 }
11322
11323 if (beforeSendFunction && beforeSendFunction.hideUpdatingOverlay) {
11324 createUpdatingOverlay = false;
11325 }
11326
11327 var options = {
11328 url: urlString,
11329 beforeSend: function(data) {
11330 if (createUpdatingOverlay) {
11331 overlay.create({ trigger:triggerData,
11332 cssStyle:{height:'100%',marginLeft:'0px', marginTop:'0px',width:'100%'}, msg : 'Please Wait'});
11333 }
11334 if ( dataType ) {
11335 data.setRequestHeader( 'ajaxDataType', dataType );
11336 }
11337 if (beforeSendFunction) {
11338 var result = beforeSendFunction(data);
11339 if(result == false) {
11340 closedelay = overlay.closeOverlay();
11341 }
11342
11343 return result;
11344 }
11345 },
11346 complete: function(data) {
11347 closedelay = overlay.closeOverlay();
11348 if (onCompleteFunction) {
11349 onCompleteFunction(data);
11350 }
11351 },
11352 dataType: dataType,
11353 data: data,
11354 contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
11355 success: function(data) {
11356 var dataType = xhtmlRequest.getResponseHeader('ajaxDataType');
11357 if ( 'json' === dataType ) {
11358 // For requests that expect a json response, session timeouts can be a problem
11359 // since the redirect check below this code will return html.
11360 if ( data.isSessionTimeout ) {
11361 if ( sessionTimeoutFunction ) {
11362 sessionTimeoutFunction( data );
11363 } else {
11364 window.location = "/shop/session/timeout/sessionTimeout.action";
11365 }
11366 return;
11367 }
11368 }
11369 if (checkForRedirect(xhtmlRequest)) {
11370 if(onSuccessFunction) {
11371 onSuccessFunction(data, urlString);
11372 }
11373 }
11374 },
11375 error: function(data, textStatus, errorThrown) {
11376 if(onErrorFunction) {
11377 onErrorFunction(data);
11378 } else {
11379 window.location = "/shop/error/handler/ajaxerror.action?status=" + textStatus + "&error=" + errorThrown + "&url=" + urlString;
11380 }
11381 },
11382 type: sendMethod
11383 };
11384
11385 xhtmlRequest = $.ajax(options);
11386}
11387
11388
11389/*
11390 * Capture the click event of all <a> tags with rel="modal" OR
11391 * all <a> tags with an href urls containing request param "modal"
11392 * with value "true" e.g. "/shop/warranties.jsp?modal=true"
11393 */
11394$(document).ready(function () {
11395 $(document).delegate("a","click",function(event){
11396 var url = $(this).attr('href');
11397 var fromBack = $(this).attr('modalBack') ? true : false;
11398 var disableClose = $(this).attr('disableModalClose') ? true : false;
11399 var showScrollbars = $(this).attr('showscrollbars') ? true : false;
11400
11401 if($(this).attr("jdwPrefix") != undefined) {
11402 $prefix = $(this).attr("jdwPrefix");
11403 var selectedColour = $("#" + $prefix + "_optionColourSelect").attr("value");
11404 var selectedSize = $("#" + $prefix + "_optionSizeSelect").attr("value");
11405 var selectedFitting = $("#" + $prefix + "_fittingSelect").attr("value");
11406
11407 $sizeDrop =$("#" + $prefix + "_optionSize").children('option[value="'+ selectedSize +'"]');
11408 $colourDrop=$("#" + $prefix + "_optionColour").children('option[value="'+ selectedColour +'"]');
11409 $fittingDrop=$("#" + $prefix + "_fitting").children('option[value="'+ selectedFitting +'"]');
11410 $currentModalContent = $('div.quickViewModalContent');
11411 }
11412
11413 if( $(this).attr('rel')=='modal' || jQuery.url.setUrl(url).param('modal')=='true' ){
11414 // prevent default behaviour on click event
11415 event.preventDefault();
11416
11417 var modalCallBack = function (data) {
11418 openModalJQ(data,url,fromBack,disableClose, showScrollbars);
11419 };
11420 modalCallBack.hideUpdatingOverlay = true;
11421
11422 ajaxGet(this, modalCallBack);
11423 }
11424 });
11425});
11426
11427$(document).ready(function() {
11428 $(document).delegate('a[rel="ajaxSubmit"]','click',function(event){
11429 event.preventDefault();
11430
11431 var urlString = $(this).attr('href');
11432 if (urlString == null || urlString.length == 0) {
11433 urlString = $(this).parents("form").attr('action');
11434 }
11435
11436 performAjaxRequest( urlString,
11437 eval($(this).attr('beforeSend')),
11438 eval($(this).attr('completeLoading')),
11439 $(this).attr('dataType'),
11440 $(this).parents("form").serialize(),
11441 eval($(this).attr('successLoading')),
11442 eval($(this).attr('errorLoading')),
11443 $(this).parents("form").prop('method'),
11444 getUniqueClass(this)
11445 );
11446 });
11447});
11448
11449
11450/*
11451 * The following functions need to run on each page load in order to maintain a user based
11452 * set of footer logos. The logos below will be removed based on the customers account type,
11453 * and also whether 3d secure has been turned on or off.
11454 */
11455
11456$(document).ready(function(){
11457 if (typeof removeCreditLogo != 'undefined') {
11458 if (removeCreditLogo == 'true') {
11459 $("div[id='personalAccount']").remove();
11460 }
11461 }
11462});
11463$(document).ready(function(){
11464 if (typeof display3DSecureFooterLogos != 'undefined') {
11465 if (display3DSecureFooterLogos == 'false') {
11466 $("img[title='Verified by Visa']").remove();
11467 $("img[title='MasterCard Securecode']").remove();
11468 }
11469 }
11470});/*
11471 * The following functions aid in the creation of Celebrus data tags.
11472 *
11473 */
11474//Function to set up object and pass it to the CSA
11475function reportAddToBasket(addedProductID, addedValue, addedCurrency,
11476 displayName, skuNum, addedQuantity, valueIsPerItem)
11477{
11478 var eventObj = new Object();
11479 eventObj.action = "add";
11480 eventObj.productID = addedProductID;
11481 eventObj.value = addedValue;
11482 eventObj.currency = addedCurrency;
11483 eventObj.productDisplayName = displayName;
11484 eventObj.skuNumber = skuNum;
11485 eventObj.quantity = addedQuantity;
11486 eventObj.valuePerItem = valueIsPerItem;
11487 if(window.JDWevent)
11488 window.JDWevent(eventObj);
11489}
11490
11491//Failed to add to basket.
11492function reportFailedToAddToBasket(addedProductID)
11493{
11494 var eventObj = new Object();
11495 eventObj.action = "failedAdd";
11496 eventObj.productID = addedProductID;
11497 if(window.JDWevent)
11498 window.JDWevent(eventObj);
11499}
11500
11501//Amend basket entry.
11502function reportAmendBasket(amendedProductID, updatedQuantity)
11503{
11504 var eventObj = new Object();
11505 eventObj.action = "amend";
11506 eventObj.productID = amendedProductID;
11507 eventObj.newQuantity = updatedQuantity;
11508 if(window.JDWevent)
11509 window.JDWevent(eventObj);
11510}
11511
11512//Remove basket entry.
11513function reportRemoveBasketItem(removedProductID)
11514{
11515 var eventObj = new Object();
11516 eventObj.action = "remove";
11517 eventObj.productID = removedProductID;
11518 if(window.JDWevent)
11519 window.JDWevent(eventObj);
11520}
11521
11522//Basket total.
11523function reportBasketTotal(basketTotalVal, basketCurrency)
11524{
11525 var eventObj = new Object();
11526 eventObj.action = "basketTotal";
11527 eventObj.totalValue = basketTotalVal;
11528 eventObj.currency = basketCurrency;
11529 if(window.JDWevent)
11530 window.JDWevent(eventObj);
11531}
11532
11533//Basket Purchased.
11534function reportPurchase(orderNum, basketTotalVal, basketCurrency)
11535{
11536 var eventObj = new Object();
11537 eventObj.action = "purchase";
11538 eventObj.orderNumber = orderNum;
11539 eventObj.totalValue = basketTotalVal;
11540 eventObj.currency = basketCurrency;
11541 if(window.JDWevent)
11542 window.JDWevent(eventObj);
11543}
11544
11545//Report 'To Follow' message displayed.
11546function reportToFollowMessage(productID, toFollowPeriod, value, currency)
11547{
11548 var targetObj = new Object();
11549 targetObj.name = "toFollowMessage";
11550 targetObj.id = productID + '_' + toFollowPeriod;
11551 targetObj.value = value + '|' + currency;
11552 targetObj.tagName = 'DIV';
11553 if(window.JDWclick)
11554 window.JDWclick(targetObj);
11555}
11556
11557//Report substitute product suggested.
11558function reportSubstituteProductSuggested(originalProductID, value, currency, substituteProductID)
11559{
11560 var targetObj = new Object();
11561 targetObj.name = "substituteProductSuggested";
11562 targetObj.id = originalProductID + '_' + substituteProductID;
11563 targetObj.value = value + '|' + currency;
11564 targetObj.tagName = 'DIV';
11565 if(window.JDWclick)
11566 window.JDWclick(targetObj);
11567}
11568
11569//Report that one of the alternative images on the product details page has been clicked.
11570function reportAltImageClick(productID, alternateImageID)
11571{
11572 var targetObj = new Object();
11573 targetObj.name = "alternativeProductDetailsImageClicked";
11574 targetObj.id = productID;
11575 targetObj.value = alternateImageID;
11576 targetObj.tagName = 'DIV';
11577 if(window.JDWclick)
11578 window.JDWclick(targetObj);
11579}
11580
11581//Report that the main images have been swapped between.
11582function reportAltImageDisplayed(productID, alternateImageID)
11583{
11584 var targetObj = new Object();
11585 targetObj.name = "alternativeProductDetailsImageChanged";
11586 targetObj.id = productID;
11587 targetObj.value = alternateImageID;
11588 targetObj.tagName = 'DIV';
11589 if(window.JDWclick)
11590 window.JDWclick(targetObj);
11591}
11592
11593//Report that a product has been added to the wish-list.
11594function reportAddToWishlistClick(productID)
11595{
11596 var targetObj = new Object();
11597 targetObj.name = "addedToWishlist";
11598 targetObj.id = productID;
11599 if(window.JDWclick)
11600 window.JDWclick(targetObj);
11601}
11602
11603
11604//Report that a product has been added to the wish-list.
11605function reportRemoveFromWishlistClick(productID)
11606{
11607 var targetObj = new Object();
11608 targetObj.name = "removedFromWishlist";
11609 targetObj.id = productID;
11610 if(window.JDWclick)
11611 window.JDWclick(targetObj);
11612}
11613
11614//Report personal account protection page click.
11615function reportPAPPageClick(pageName)
11616{
11617 var targetObj = new Object();
11618 targetObj.id = "stid_paptrans_" + pageName;
11619 targetObj.name = "stid_paptrans";
11620 targetObj.value = pageName;
11621 targetObj.tagName = 'DIV';
11622 if(window.JDWclick)
11623 window.JDWclick(targetObj);
11624}
11625
11626//Report a click on Amplience Functionality. Captured using the Amplience invokeTenCMSEvent JS
11627//function in Amplience.html.
11628function reportAmplienceClick(amplienceEventObject) {
11629 var targetObj = new Object();
11630 url = $.trim(amplienceEventObject.url);
11631
11632 targetObj.name = url;
11633 targetObj.href = url;
11634 targetObj.value = url;
11635 targetObj.id = "amplienceClick";
11636
11637 //using ^ as a separator in Celebrus, don't change without also changing Celebrus.
11638 targetObj.id += "^" + ($.trim(amplienceEventObject.SSID) == "" ? "undefined" : $.trim(amplienceEventObject.SSID));
11639 targetObj.id += "^" + ($.trim(amplienceEventObject.element) == "" ? "undefined" : $.trim(amplienceEventObject.element));
11640 targetObj.id += "^" + ($.trim(amplienceEventObject.eventName) == "" ? "undefined" : $.trim(amplienceEventObject.eventName));
11641 targetObj.id += "^" + ($.trim(amplienceEventObject.moduleID) == "" ? "undefined" : $.trim(amplienceEventObject.moduleID));
11642 targetObj.id += "^" + ($.trim(amplienceEventObject.parent) == "" ? "undefined" : $.trim(amplienceEventObject.parent));
11643 targetObj.id += "^" + ($.trim(amplienceEventObject.value) == "" ? "undefined" : $.trim(amplienceEventObject.value));
11644
11645 if (window.JDWclick)
11646 window.JDWclick(targetObj);
11647}
11648
11649//Reports slider product displayed.
11650function reportSliderProduct(url, productId, productIndex, prefix) {
11651 var targetObj = new Object();
11652
11653 targetObj.name = url;
11654 targetObj.href = url;
11655 targetObj.value = url;
11656 targetObj.id = prefix + "SliderProduct_" + productId + "_" + productIndex;
11657
11658 if (window.JDWclick)
11659 window.JDWclick(targetObj);
11660}
11661
11662//Create a Celebrus target object
11663function createTargetObj(type, category, selection, remainder, state, href) {
11664 var targetObj = {};
11665 targetObj.tagName = "DIV";
11666 var args = Array.prototype.slice.call(arguments);
11667 var length = args.length;
11668 targetObj.id = "celid";
11669 for (var i=0; i<length-1; i++){
11670 var val = args[i];
11671 if (val != null) targetObj.id = targetObj.id + "_" + $.trim(val.toLowerCase());
11672 }
11673 targetObj.name = $.trim(href);
11674 targetObj.href = $.trim(href);
11675 targetObj.value = $.trim(href);
11676 return targetObj;
11677}
11678
11679//Report that a single select refinement group category has been clicked
11680function reportSingleSelectRefinementGroupCategoryClicked(link) {
11681 if(window.JDWclick) {
11682 var $link = $(link);
11683 var selection = $.trim($link.clone().children().remove(".count").end().text()).replace(/[\n\r]+\-/g, "");
11684 var href = document.getElementById($link.attr('id')).href; // non jQuery so that the absolute path is retrieved consistently
11685 if (selection != "clear") {
11686 var remainder = $link.clone().children(".count").text().replace(new RegExp("[()]","gi"), "");
11687 var category = $link.closest(".availableFiltersContainer").prev(".refinementHeader").children("span:first").text();
11688 if($link.closest("ul").hasClass("checkList"))
11689 var state = $link.hasClass("checked") ? "off" : "on";
11690 else
11691 var state = "on";
11692 window.JDWclick(createTargetObj('cmslhnr', category, selection, remainder, state, href));
11693 }
11694 else {
11695 if($link.parent().hasClass("refinementHeader"))
11696 reportRefinementGroupClearClicked(link);
11697 else
11698 reportSelectedFilterClearClicked(link);
11699 }
11700 }
11701}
11702
11703//Report that a value has been selected from the product window Sort By list
11704function reportSortBySelected(selected) {
11705 if(window.JDWclick)
11706 var href = window.location.protocol + '//' + window.location.host + $(selected).attr('value'); // need to construct the url because the relative path is from a value attribute rather than href
11707 window.JDWclick(createTargetObj("cmssb", null, $(selected).find("option:selected").text(), null, "on", href));
11708}
11709
11710//Report that a value has been selected from the product window custom drop down Sort By list
11711function reportCustomDropDownSortBySelected(selected) {
11712 if(window.JDWclick)
11713 var href = window.location.protocol + '//' + window.location.host + $(selected).attr('data-jdw-link'); // need to construct the url because the relative path is from a data attribute rather than href
11714 window.JDWclick(createTargetObj("cmssb", null, $(selected).text(), null, "on", href));
11715}
11716
11717//Report that a value has been selected from the product window Products Per Page list
11718function reportProductsPerPageSelected(selected) {
11719 if(window.JDWclick) {
11720 var href = window.location.protocol + '//' + window.location.host + $(selected).attr('value');
11721 var option = $(selected).find("option:selected").text().replace(" products", "");
11722 window.JDWclick(createTargetObj("cmsppp", null, option, null, "on", href));
11723 }
11724}
11725
11726//Report that a filtering group concertina has been clicked
11727function reportFilteringGroupConcertinaClicked(filterGroup) {
11728 if(window.JDWclick) {
11729 var $fg = $(filterGroup);
11730 window.JDWclick(createTargetObj("cmslhcon", $fg.text(), null, null, (!$fg.hasClass("active") ? "on" : "off"), null));
11731 }
11732}
11733
11734//Report that a filtering group browse categories concertina has been clicked
11735function reportFilteringGroupBrowseCategoriesConcertinaClicked(filterGroup) {
11736 if(window.JDWclick) {
11737 var $fg = $(filterGroup);
11738 window.JDWclick(createTargetObj("cmsbccon", $fg.text(), null, null, (!$fg.hasClass("active") ? "on" : "off"), null));
11739 }
11740}
11741
11742//Report that a navigation page link has been clicked
11743function reportNavPageLinkClicked(link) {
11744 if(window.JDWclick) {
11745 var $link = $(link);
11746 var method = link.id.substring(link.id.indexOf("-") + 1);
11747 var pageno;
11748 var href = document.getElementById($link.attr('id')).href;
11749 if (!href) href=document.getElementById($link.parent().attr('id')).href; // mobile
11750 if(method === "Next" || method === "nextResults") {
11751 method = "next";
11752 pageno = $link.parent().siblings('span.current').next().children('a:first').text();
11753 (pageno=="" ? pageno="na" : false); // mobile does not identify page numbers
11754 } else if(method === "Prev" || method === "previousResults") {
11755 method = "prev";
11756 pageno = $link.parent().siblings('span.current').prev().children('a:first').text();
11757 (pageno=="" ? pageno="na" : false);
11758 } else {
11759 pageno = method;
11760 method = "direct";
11761 }
11762 window.JDWclick(createTargetObj("cmspn", method, pageno, null, "on", href));
11763 }
11764}
11765
11766//Report that products are displayed in the shop window
11767function reportProductsDisplayed(productListTotal) {
11768 if(window.JDWclick) {
11769 window.JDWclick(createTargetObj("cmspl", productListTotal.toString(), null, null, "on", null));
11770 }
11771}
11772
11773//Report that a price slide change has been made
11774function reportPriceSliderChanged(values) {
11775 if(window.JDWclick)
11776 window.JDWclick(createTargetObj("cmslhnps", "priceslider", (values[0] + "-" + values[1]), "na", "on", null));
11777}
11778
11779//Report that the clear all link has been clicked
11780function reportClearAllClicked(link) {
11781 if(window.JDWclick){
11782 var $link = $(link);
11783 var href = document.getElementById($link.attr('id')).href;
11784 window.JDWclick(createTargetObj("cmslhnca", "all", "clear", "na", "off", href));
11785 }
11786}
11787
11788//Report that the clear link for a refinement group has been clicked
11789function reportRefinementGroupClearClicked(link) {
11790 if(window.JDWclick){
11791 var $link = $(link);
11792 var href = document.getElementById($link.attr('id')).href;
11793 window.JDWclick(createTargetObj("cmslhncg", $link.prev().text(), "clear", "na", "off", href));
11794 }
11795}
11796
11797//Report that the clear link for a selected filter has been clicked
11798function reportSelectedFilterClearClicked(link) {
11799 if(window.JDWclick){
11800 var $link = $(link);
11801 var href = document.getElementById($link.attr('id')).href;
11802 window.JDWclick(createTargetObj("cmslhncp",
11803 $(link).closest("li").text().replace(new RegExp("(clear)", "gi"), ""),
11804 "clear", "na", "off", href));
11805 }
11806}
11807
11808//Report that the clear link for a selected filter has been clicked
11809function reportOffCanvasSelectedFilterClearClicked(link) {
11810 if(window.JDWclick){
11811 var href = document.getElementById($(link).attr('id')).href;
11812 window.JDWclick(createTargetObj("cmslhncp",
11813 $.trim($(link).text().replace(new RegExp(" \\(.*\\)", "gi"), "")),
11814 "clear", "na", "off", href));
11815 }
11816}
11817
11818//Report that refine search has been clicked
11819function reportRefineSearchClicked(selected) {
11820 if(window.JDWclick) {
11821 var href = window.location.protocol + '//' + window.location.host + $(selected).attr('value');
11822 window.JDWclick(createTargetObj("cmslhnsr", $(selected).find("option:first").text(),
11823 $(selected).find("option:selected").text(), "na", "on", href));
11824 }
11825}
11826
11827//Report that refine search has been clicked
11828function reportOffCanvasRefineSearchClicked(selected) {
11829 if(window.JDWclick) {
11830 var href = window.location.protocol + '//' + window.location.host + $(selected).attr('href');
11831 window.JDWclick(createTargetObj("cmslhnsr", $(selected).closest("ul").attr('id').replace(new RegExp("-refinement", "gi"), ""),
11832 $(selected).text().replace(new RegExp(" \\(.*\\)", "gi"), ""), "na", "on", href));
11833 }
11834}
11835
11836//Report that an autocomplete text box option has been selected
11837function reportTextChanged(text, id, name)
11838{
11839 var targetObj = new Object();
11840 targetObj.name = name;
11841 targetObj.id = id;
11842 targetObj.value = text;
11843 targetObj.tagName = 'input';
11844 targetObj.type = 'text';
11845 if(window.JDWtextchange)
11846 window.JDWtextchange(targetObj);
11847}/*
11848 * The following functions aid in the creation of Celebrus events.
11849 *
11850 */
11851//Function to set up object and pass it to the CSA
11852function celReportAddToBasket(addedProductID, addedValue, addedCurrency,
11853 displayName, skuNum, addedQuantity, valueIsPerItem)
11854{
11855 try {
11856 reportAddToBasket(addedProductID, addedValue, addedCurrency,
11857 displayName, skuNum, addedQuantity, valueIsPerItem);
11858 } catch (err) {
11859 }
11860}
11861
11862//Failed to add to basket.
11863function celReportFailedToAddToBasket(addedProductID)
11864{
11865 try {
11866 reportFailedToAddToBasket(addedProductID);
11867 } catch (err) {
11868 }
11869}
11870
11871//Amend basket entry.
11872function celReportAmendBasket(amendedProductID, updatedQuantity)
11873{
11874 try {
11875 reportAmendBasket(amendedProductID, updatedQuantity);
11876 } catch (err) {
11877 }
11878}
11879
11880//Remove basket entry.
11881function celReportRemoveBasketItem(removedProductID)
11882{
11883 try {
11884 reportRemoveBasketItem(removedProductID);
11885 } catch (err) {
11886 }
11887}
11888
11889//Basket total.
11890function celReportBasketTotal(basketTotalVal, basketCurrency)
11891{
11892 try {
11893 reportBasketTotal(basketTotalVal, basketCurrency);
11894 } catch (err) {
11895 }
11896}
11897
11898//Basket purchased.
11899function celReportPurchase(orderNum, basketTotalVal, basketCurrency)
11900{
11901 try {
11902 reportPurchase(orderNum, basketTotalVal, basketCurrency);
11903 } catch (err) {
11904 }
11905}
11906
11907//Report 'To Follow' message displayed.
11908function celReportToFollowMessage(productID, toFollowPeriod, value, currency)
11909{
11910 try {
11911 reportToFollowMessage(productID, toFollowPeriod, value, currency);
11912 } catch (err) {
11913 }
11914}
11915
11916//Report substitute product suggested.
11917function celReportSubstituteProductSuggested(originalProductID, value, currency, substituteProductID)
11918{
11919 try {
11920 reportSubstituteProductSuggested(originalProductID, value, currency, substituteProductID);
11921 } catch (err) {
11922 }
11923}
11924
11925//Report that one of the alternative images on the product details page has been clicked.
11926function celReportAltImageClick(productID, alternateImageID)
11927{
11928 try {
11929 reportAltImageClick(productID, alternateImageID);
11930 } catch (err) {
11931 }
11932}
11933
11934//Report that the main image on the product details page has been changed.
11935function celReportAltImageDisplayed(productID, alternateImageID)
11936{
11937 try {
11938 reportAltImageDisplayed(productID, alternateImageID);
11939 } catch (err) {
11940 }
11941}
11942
11943//Report product added to wishlist.
11944function celReportAddToWishlist(productCode)
11945{
11946 try {
11947 reportAddToWishlistClick(productCode);
11948 } catch (err) {
11949 }
11950}
11951
11952
11953function celReportRemoveFromWishlist(productCode){
11954 try {
11955 reportRemoveFromWishlistClick(productCode);
11956 } catch (err) {
11957 }
11958}
11959
11960//Report personal account protection page click.
11961function celReportPAPPageClick(pageName)
11962{
11963 try {
11964 reportPAPPageClick(pageName);
11965 } catch (err) {
11966 }
11967}
11968
11969//Report that a single select refinement group category has been clicked
11970function celReportSingleSelectRefinementGroupCategoryClicked(link) {
11971 try {
11972 reportSingleSelectRefinementGroupCategoryClicked(link);
11973 } catch (err) {
11974 }
11975}
11976
11977//Report that a value has been selected from the product window Sort By list
11978function celReportSortBySelected(selected) {
11979 try {
11980 reportSortBySelected(selected);
11981 } catch (err) {
11982 }
11983}
11984
11985//Report that a value has been selected from the product window custom drop down Sort By list
11986function celReportCustomDropDownSortBySelected(selected) {
11987 try {
11988 reportCustomDropDownSortBySelected(selected);
11989 } catch (err) {
11990 }
11991}
11992
11993//Report that a value has been selected from the product window Products Per Page list
11994function celReportProductsPerPageSelected(selected) {
11995 try {
11996 reportProductsPerPageSelected(selected);
11997 } catch (err) {
11998 }
11999}
12000
12001//Report that a filtering group concertina has been clicked
12002function celReportFilteringGroupConcertinaClicked(filterGroup) {
12003 try {
12004 reportFilteringGroupConcertinaClicked(filterGroup);
12005 } catch (err) {
12006 }
12007}
12008
12009//Report that a filtering group browse categories concertina has been clicked
12010function celReportFilteringGroupBrowseCategoriesConcertinaClicked(filterGroup) {
12011 try {
12012 reportFilteringGroupBrowseCategoriesConcertinaClicked(filterGroup);
12013 } catch (err) {
12014 }
12015}
12016
12017//Report that a navigation page link has been clicked
12018function celReportNavPageLinkClicked(link) {
12019 try {
12020 reportNavPageLinkClicked(link);
12021 } catch (err) {
12022 }
12023}
12024
12025//Report that products are displayed in the shop window
12026function celReportProductsDisplayed(productListTotal) {
12027 try {
12028 reportProductsDisplayed(productListTotal);
12029 } catch (err) {
12030 }
12031}
12032
12033//Report that a price slide change has been made
12034function celReportPriceSliderChanged(values) {
12035 try {
12036 reportPriceSliderChanged(values);
12037 } catch (err) {
12038 }
12039}
12040
12041//Report that a price slide change has been made
12042function celReportClearAllClicked(link) {
12043 try {
12044 reportClearAllClicked(link);
12045 } catch (err) {
12046 }
12047}
12048
12049//Report that the clear link for a particular refinement has been clicked
12050function celReportRefinementGroupClearClicked(link) {
12051 try {
12052 reportRefinementGroupClearClicked(link);
12053 } catch (err) {
12054 }
12055}
12056
12057//Report that the clear link for a refinement group has been clicked
12058function celReportSelectedFilterClearClicked(link) {
12059 try {
12060 reportSelectedFilterClearClicked(link);
12061 } catch (err) {
12062 }
12063}
12064
12065//Report that the clear link for a refinement group has been clicked
12066function celReportOffCanvasSelectedFilterClearClicked(link) {
12067 try {
12068 reportOffCanvasSelectedFilterClearClicked(link);
12069 } catch (err) {
12070 }
12071}
12072
12073//Report that refine search has been clicked
12074function celReportRefineSearchClicked(selected) {
12075 try {
12076 reportRefineSearchClicked(selected);
12077 } catch (err) {
12078 }
12079}
12080
12081//Report that refine search has been clicked
12082function celReportOffCanvasRefineSearchClicked(selected) {
12083 try {
12084 reportOffCanvasRefineSearchClicked(selected);
12085 } catch (err) {
12086 }
12087}
12088
12089//Report that an autocomplete text box option has been selected
12090function celReportTextChanged(text, id, name) {
12091 try {
12092 reportTextChanged(text, id, name);
12093 } catch (err) {
12094 }
12095}
12096
12097//Takes the object generated by Amplience analytic events and converts it into Celebrus clicks events.
12098function celReportAmplienceClick(amplienceEventObject) {
12099 try {
12100 reportAmplienceClick(amplienceEventObject);
12101 } catch (err) {
12102 }
12103}
12104
12105//Reports outfit builder slider product displayed
12106function celReportOutfitSliderProduct(url, productId, productIndex) {
12107 try {
12108 reportSliderProduct(url, productId, productIndex, "outfit");
12109 } catch (err) {
12110 }
12111}
12112
12113//Reports slider product displayed
12114function celReportAffinitySliderProduct(url, productId, productIndex) {
12115 try {
12116 reportSliderProduct(url, productId, productIndex, "affinity");
12117 } catch (err) {
12118 }
12119}
12120/**
12121 * PASSWORD STRENGTH INDICATOR
12122 * Display an indication of the strength of the password as it is being typed.
12123 *
12124 * To use this, supply an element with a class of `js-password-strength`
12125 * along with a `data-target` attribute that references the unique ID
12126 * of the password input to test.
12127 *
12128 * You can adjust the breakpoints for the scores by adding data-score-ok="X"
12129 * and data-score-good="X" (where X is a number between 1 and 10) to the password
12130 * strength element. You can also control the messages for the various warnings/prompts
12131 * with data attributes
12132 *
12133 * e.g.
12134 * <label for="my-password">Password</label>
12135 * <input type="password" id="my-password" />
12136 * <div class="js-password-strength password-strength" data-target="my-password"></div>
12137 */
12138
12139var jdw = jdw || {};
12140
12141jdw.PasswordStrength = (function () {
12142 "use strict";
12143
12144 var PASSWORD_STRENGTH_SELECTOR = ".js-password-strength";
12145 var PASSWORD_INIT_CLASS = "input-has-strength";
12146 var STRENGTH_FLAG_INVALID = "invalid";
12147 var STRENGTH_FLAG_POOR = "poor";
12148 var STRENGTH_FLAG_OK = "ok";
12149 var STRENGTH_FLAG_GOOD = "good";
12150 var SCORE_MAX = 10;
12151 var SCORE_HAS_LOWER = 2;
12152 var SCORE_HAS_UPPER = 2;
12153 var SCORE_HAS_NUMBER = 2;
12154 var SCORE_HAS_OTHER = 3;
12155 var SCORE_HAS_ALL = 4;
12156
12157 if ('NodeList' in window && !NodeList.prototype.forEach) {
12158 NodeList.prototype.forEach = function (callback, thisArg) {
12159 thisArg = thisArg || window;
12160 for (var i = 0; i < this.length; i++) {
12161 callback.call(thisArg, this[i], i, this);
12162 }
12163 };
12164 }
12165
12166 /**
12167 * A simple hash implementation to turn a string into a 32 bit signed integer
12168 *
12169 * @returns {number}
12170 */
12171 function getHashCode(string) {
12172 var hash = 0;
12173 var i;
12174 var chr;
12175
12176 if (string.length === 0) {
12177 return hash;
12178 }
12179
12180 for (i = 0; i < string.length; i++) {
12181 chr = string.charCodeAt(i);
12182 hash = ((hash << 5) - hash) + chr;
12183 hash |= 0;
12184 }
12185
12186 return hash;
12187 }
12188
12189 /**
12190 * Deltas between a hashed list of passwords.
12191 * https://jdwilliams.atlassian.net/wiki/spaces/UT/pages/435650672/How+to+hash+and+minify+a+list+of+bad+passwords
12192 */
12193 function buildHashedPasswordsFromDelta(deltaPasswords, firstPassword) {
12194 var password;
12195 return deltaPasswords.map(function (delta) {
12196 password = firstPassword + delta;
12197 firstPassword = password;
12198 return password;
12199 });
12200 }
12201
12202 function hasUpperCase(string) {
12203 return (string.match(/[A-Z]/) !== null);
12204 }
12205
12206 function hasLowerCase(string) {
12207 return (string.match(/[a-z]/) !== null);
12208 }
12209
12210 function hasNumber(string) {
12211 return (string.match(/[0-9]/) !== null);
12212 }
12213
12214 function hasOther(string) {
12215 return (string.match(/[^0-9A-Za-z]/) !== null);
12216 }
12217
12218 /**
12219 * Calculate the score for a given password
12220 *
12221 * @param password
12222 * @param minLength
12223 * @returns {number}
12224 */
12225 function calculateScore(password, minLength) {
12226 var numberOfCharacters = password.length;
12227
12228 return Math.min(
12229 Math.min(SCORE_MAX, numberOfCharacters),
12230 (
12231 Math.max(numberOfCharacters - minLength, 0) +
12232 (hasUpperCase(password) ? SCORE_HAS_UPPER : 0) +
12233 (hasLowerCase(password) ? SCORE_HAS_LOWER : 0) +
12234 (hasNumber(password) ? SCORE_HAS_NUMBER : 0) +
12235 (hasOther(password) ? SCORE_HAS_OTHER : 0) +
12236 ((
12237 hasUpperCase(password) &&
12238 hasLowerCase(password) &&
12239 hasNumber(password) &&
12240 hasOther(password)
12241 ) ? SCORE_HAS_ALL : 0)
12242 )
12243 );
12244 }
12245
12246 /**
12247 * Calculate the strength of a password and update the strength helper accordingly
12248 * Also disables any controlled inputs
12249 */
12250 function updateStrength(strengthHelper, password, suppliedOptions) {
12251 var isCommonPassword = false;
12252 var options = {
12253 // add your invalid characters here
12254 invalidCharacerRegEx: ".*[£¬].*",
12255 endInASpaceRegEx: "^.* $",
12256 topPasswords: [],
12257 hashedPasswords: [],
12258 minLength: 8,
12259 scoreOk: 4,
12260 scoreGood: 9,
12261 messageEndsInASpace: "Password must not end with a space.",
12262 messageInvalid: "Please use at least 8 characters.",
12263 messageBadchar: "This password contains invalid characters. Please try another.",
12264 messageCommon: "This is a common password. Easy to guess.",
12265 messagePoor: "This is easy to guess.",
12266 messagePoorSuggestionDefault: "Try making it longer.",
12267 messagePoorSuggestionNoNumbers: "Try adding a number.",
12268 messagePoorSuggestionNoUppercase: "Try adding an uppercase letter.",
12269 messageOk: "Good password. Difficult to guess.",
12270 messageGood: "Excellent password! Very hard to guess."
12271 };
12272
12273 // merge the supplied options with the default options
12274 for (var attr in options) {
12275 if (suppliedOptions.hasOwnProperty(attr) && suppliedOptions[attr]) {
12276 options[attr] = suppliedOptions[attr];
12277 }
12278 }
12279
12280 // check against a list of common passwords once we hit the min length
12281 if (password.length >= options.minLength) {
12282 if (options.topPasswords.length > 0) {
12283 isCommonPassword = (options.topPasswords.indexOf(password) > -1);
12284 } else if (options.hashedPasswords.length > 0) {
12285 isCommonPassword = (options.hashedPasswords.indexOf(getHashCode(password)) > -1);
12286 }
12287 }
12288
12289 var score = calculateScore(password, options.minLength);
12290
12291 strengthHelper.dataset.score = score;
12292 if (regexMatches(password, options.invalidCharacerRegEx)) {
12293 // not long enough to submit
12294 strengthHelper.dataset.strength = STRENGTH_FLAG_INVALID;
12295 strengthHelper.innerText = options.messageBadchar;
12296 } else if (password.length < options.minLength) {
12297 // not long enough to submit
12298 strengthHelper.dataset.strength = STRENGTH_FLAG_INVALID;
12299 strengthHelper.innerText = options.messageInvalid;
12300 } else if (regexMatches(password, options.endInASpaceRegEx)) {
12301 // not long enough to submit
12302 strengthHelper.dataset.strength = STRENGTH_FLAG_INVALID;
12303 strengthHelper.innerText = options.messageEndsInASpace;
12304 } else if (isCommonPassword) {
12305 // we've found a match in our list of common passwords
12306 strengthHelper.dataset.strength = STRENGTH_FLAG_POOR;
12307 strengthHelper.innerText = options.messageCommon;
12308 } else if (score <= options.scoreOk) {
12309 // password is acceptable but we can offer some hints to make it stronger
12310 strengthHelper.dataset.strength = STRENGTH_FLAG_POOR;
12311
12312 var suggestion = options.messagePoorSuggestionDefault;
12313 if (password.length > options.minLength) {
12314 if (!hasNumber(password)) {
12315 suggestion = options.messagePoorSuggestionNoNumbers;
12316 } else if (!hasUpperCase(password)) {
12317 suggestion = options.messagePoorSuggestionNoUppercase;
12318 }
12319 }
12320 strengthHelper.innerText = options.messagePoor + " " + suggestion;
12321 } else if (score <= options.scoreGood) {
12322 // password is ok but could be better
12323 strengthHelper.dataset.strength = STRENGTH_FLAG_OK;
12324 strengthHelper.innerText = options.messageOk;
12325 } else {
12326 // password is nice and strong
12327 strengthHelper.dataset.strength = STRENGTH_FLAG_GOOD;
12328 strengthHelper.innerText = options.messageGood;
12329 }
12330 }
12331
12332 function regexMatches(password, regexCheck) {
12333 var re = new RegExp(regexCheck);
12334 return re.test(password);
12335 }
12336
12337 /**
12338 * Build an options object to be passed through to the updateStrength function
12339 *
12340 * @param strengthHelper
12341 * @param passwordInput
12342 */
12343 function setOptions(strengthHelper, passwordInput) {
12344 var dataset = strengthHelper.dataset;
12345 var deltaPasswords = dataset.deltaPasswords ?
12346 dataset.deltaPasswords.split(",").map(Number) : [];
12347 var firstPassword = parseInt(dataset.firstPassword) || null;
12348 var customInvalidMessage = "Please use at least " +
12349 passwordInput.minLength + " characters.";
12350 var customInvalidCharRegEx = ".*[£¬].*"
12351 var options = {};
12352
12353 options.endInASpaceRegEx = dataset.endInASpaceRegEx ? dataset.endInASpaceRegEx: "^.* $",
12354 options.invalidCharacerRegEx = dataset.invalidCharacerRegEx ? dataset.invalidCharacerRegEx: customInvalidCharRegEx;
12355 options.topPasswords = dataset.topPasswords ?
12356 dataset.topPasswords.split(",") : [];
12357 options.hashedPasswords = dataset.hashedPasswords ?
12358 dataset.hashedPasswords.split(",").map(Number) : [];
12359 options.minLength = passwordInput.minLength;
12360 options.scoreOk = dataset.scoreOk;
12361 options.scoreGood = dataset.scoreGood;
12362 options.messageBadchar = dataset.messageBadchar;
12363 options.messageInvalid = dataset.messageInvalid || customInvalidMessage;
12364 options.messageEndsInASpace = dataset.messageEndsInASpace;
12365 options.messageCommon = dataset.messageCommon;
12366 options.messagePoor = dataset.messagePoor;
12367 options.messagePoorSuggestionDefault = dataset.messagePoorSuggestionDefault;
12368 options.messagePoorSuggestionNoNumbers = dataset.messagePoorSuggestionNoNumbers;
12369 options.messagePoorSuggestionNoUppercase = dataset.messagePoorSuggestionNoUppercase;
12370 options.messageOk = dataset.messageOk;
12371 options.messageGood = dataset.messageGood;
12372
12373 // build hashed passwords if necessary
12374 if (options.topPasswords.length === 0 &&
12375 options.hashedPasswords.length === 0 &&
12376 deltaPasswords.length > 0 &&
12377 firstPassword !== null) {
12378 options.hashedPasswords = buildHashedPasswordsFromDelta(deltaPasswords, firstPassword);
12379 }
12380
12381 return options;
12382 }
12383
12384 function init() {
12385 var strengthHelpers = document.querySelectorAll(PASSWORD_STRENGTH_SELECTOR);
12386
12387 strengthHelpers.forEach(function (strengthHelper) {
12388 var passwordInput = document.getElementById(strengthHelper.dataset.target);
12389
12390 if (!passwordInput || passwordInput.classList.contains(PASSWORD_INIT_CLASS)) {
12391 return;
12392 }
12393
12394 var options = setOptions(strengthHelper, passwordInput);
12395
12396 passwordInput.classList.add(PASSWORD_INIT_CLASS);
12397
12398 passwordInput.addEventListener("input", function () {
12399 updateStrength(strengthHelper, passwordInput.value, options);
12400 });
12401 });
12402 }
12403
12404 return {
12405 init: init
12406 };
12407})();/*
12408 * PASSWORD TOGGLER
12409 * Toggles a password field to text and back again
12410 *
12411 * To use this, supply an element with a class of `js-password-toggler`
12412 * along with a `data-target` attribute that references the unique ID
12413 * of the password input to toggle.
12414 *
12415 * e.g.
12416 * <input type="password" id="my-password" />
12417 * <span class="js-password-toggler" data-target="my-password">show</span>
12418 */
12419
12420var jdw = jdw || {};
12421
12422jdw.PasswordToggler = (function () {
12423 "use strict";
12424
12425 var PASSWORD_TOGGLER_SELECTOR = ".js-password-toggler";
12426 var TOGGLER_ACTIVE_CLASS = "password-toggler-is-active";
12427 var INPUT_INIT_CLASS = "input-has-password-toggler";
12428
12429 if ('NodeList' in window && !NodeList.prototype.forEach) {
12430 NodeList.prototype.forEach = function (callback, thisArg) {
12431 thisArg = thisArg || window;
12432 for (var i = 0; i < this.length; i++) {
12433 callback.call(thisArg, this[i], i, this);
12434 }
12435 };
12436 }
12437
12438 function handleToggleClick(toggler, passwordInput) {
12439 if (toggler.classList.contains(TOGGLER_ACTIVE_CLASS)) {
12440 toggler.classList.remove(TOGGLER_ACTIVE_CLASS);
12441 toggler.innerText = "show";
12442 passwordInput.type = "password";
12443 } else {
12444 toggler.classList.add(TOGGLER_ACTIVE_CLASS);
12445 toggler.innerText = "hide";
12446 passwordInput.type = "text";
12447 }
12448
12449 passwordInput.focus();
12450 }
12451
12452 function init() {
12453 var togglers = document.querySelectorAll(PASSWORD_TOGGLER_SELECTOR);
12454
12455 togglers.forEach(function (toggler) {
12456 var passwordInput = document.getElementById(toggler.dataset.target);
12457
12458 if (!passwordInput || passwordInput.classList.contains(INPUT_INIT_CLASS)) {
12459 return;
12460 }
12461
12462 passwordInput.classList.add(INPUT_INIT_CLASS);
12463
12464 toggler.addEventListener("click", function () {
12465 handleToggleClick(toggler, passwordInput);
12466 });
12467 });
12468 }
12469
12470 return {
12471 init: init
12472 };
12473}());</script>
12474<!-- RESPONSIVE FOOTER END -->
12475 </body>
12476</html>
12477
12478====
12479Sniffed By Stream, Only Spread For Research Purpose.